// //----------------------------------------------------------------------------- void CPUTDropdown::CalculateTrayRect(CPUT_RECT &inner, CPUT_RECT &outer) { int maxItemWidth, maxItemHeight; CalculateMaxItemSize(maxItemWidth, maxItemHeight); CPUT_RECT innerReadout, outerReadout; CalculateReadoutRect(innerReadout, outerReadout); // locations outer.x = outerReadout.x + 5; outer.y = outerReadout.y + outerReadout.height; inner.x = outer.x + mpDropdownIdleImageSizeList[CLeftMid].width; inner.y = outer.y + CPUT_DROPDOWN_TEXT_PADDING; // dimension inner.width = maxItemWidth + 2*CPUT_DROPDOWN_TEXT_PADDING; inner.height = (int)((mpListOfSelectableItems.size())*(maxItemHeight+2*CPUT_DROPDOWN_TEXT_PADDING)); outer.width = inner.width + mpDropdownIdleImageSizeList[CLeftMid].width + mpDropdownIdleImageSizeList[CRightMid].width; outer.height = inner.height + mpDropdownIdleImageSizeList[CLeftBot].height; }
// //----------------------------------------------------------------------------- void CPUTDropdown::CalculateReadoutRect(CPUT_RECT &inner, CPUT_RECT &outer) { bool ButtonIsBiggerThanText = false; // calculate outer dimensions outer.x = mControlDimensions.x; outer.y = mControlDimensions.y; int maxItemSizeWidth, maxItemSizeHeight; CalculateMaxItemSize(maxItemSizeWidth, maxItemSizeHeight); if( (maxItemSizeHeight+2*CPUT_DROPDOWN_TEXT_PADDING) < mpDropdownIdleImageSizeList[CButtonUp].height) { ButtonIsBiggerThanText = true; } outer.width = mpDropdownIdleImageSizeList[CLeftTop].width + CPUT_DROPDOWN_TEXT_PADDING + maxItemSizeWidth + CPUT_DROPDOWN_TEXT_PADDING + mpDropdownIdleImageSizeList[CButtonUp].width + mpDropdownIdleImageSizeList[CRightTop].width; if(ButtonIsBiggerThanText) { outer.height = mpDropdownIdleImageSizeList[CLeftTop].height + mpDropdownIdleImageSizeList[CButtonUp].width + mpDropdownIdleImageSizeList[CLeftBot].height; } else { outer.height = mpDropdownIdleImageSizeList[CLeftTop].height + CPUT_DROPDOWN_TEXT_PADDING + maxItemSizeHeight + CPUT_DROPDOWN_TEXT_PADDING + mpDropdownIdleImageSizeList[CLeftBot].height; } // calculate the inner dimensions inner.x = mControlDimensions.x + mpDropdownIdleImageSizeList[CLeftTop].width + CPUT_DROPDOWN_TEXT_PADDING; inner.y = mControlDimensions.y + mpDropdownIdleImageSizeList[CLeftTop].height; if(ButtonIsBiggerThanText) { inner.width = CPUT_DROPDOWN_TEXT_PADDING + maxItemSizeWidth + CPUT_DROPDOWN_TEXT_PADDING + mpDropdownIdleImageSizeList[CButtonUp].width; inner.height = mpDropdownIdleImageSizeList[CButtonUp].height; } else { inner.width = CPUT_DROPDOWN_TEXT_PADDING + maxItemSizeWidth + CPUT_DROPDOWN_TEXT_PADDING + mpDropdownIdleImageSizeList[CButtonUp].width; inner.height = maxItemSizeHeight + 2*CPUT_DROPDOWN_TEXT_PADDING; } }
// Recalculate all the quads used to draw this control //-------------------------------------------------------------------------------- void CPUTDropdown::Recalculate() { mpDropdownIdleSizeList; // calculate height/width of dropdown's interior based on string or button size CPUT_RECT inner, outer; CalculateReadoutRect(inner, outer); // calculate the pieces we'll need to rebuild int middleWidth = inner.width; int middleHeight = inner.height; // TODO: this should be calculated like const int mSmallestTopSizeIdle = mpDropdownIdleImageSizeList[0].height; const int mSmallestLeftSizeIdle =mpDropdownIdleImageSizeList[0].width; // clear and allocate the buffers const int VertexCount = 18*3*2; SAFE_DELETE_ARRAY(mpMirrorBufferActive); mpMirrorBufferActive = new CPUTGUIVertex[VertexCount]; SAFE_DELETE_ARRAY(mpMirrorBufferDisabled); mpMirrorBufferDisabled = new CPUTGUIVertex[VertexCount]; // // delete the old button quads for the middle sections //result = UnRegisterResizableInstanceQuads(); // Calculate the selected item area images // Idle button quads // left AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 0*6, (float)mControlDimensions.x, (float)mControlDimensions.y, (float) mpDropdownIdleImageSizeList[0].width, (float) mpDropdownIdleImageSizeList[0].height, mpDropdownUVCoords_active[2*0], mpDropdownUVCoords_active[2*0+1] ); AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 1*6, (float)mControlDimensions.x, (float)mControlDimensions.y+mSmallestTopSizeIdle, (float) mpDropdownIdleImageSizeList[1].width, (float) middleHeight, mpDropdownUVCoords_active[2*1], mpDropdownUVCoords_active[2*1+1] ); mpDropdownIdleSizeList[1].height = middleHeight; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 2*6, (float)mControlDimensions.x, (float)mControlDimensions.y+mSmallestTopSizeIdle+middleHeight, (float) mpDropdownIdleImageSizeList[2].width, (float) mpDropdownIdleImageSizeList[2].height, mpDropdownUVCoords_active[2*2], mpDropdownUVCoords_active[2*2+1] ); // middle AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 3*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle, (float)mControlDimensions.y, (float) middleWidth, (float) mpDropdownIdleImageSizeList[3].height, mpDropdownUVCoords_active[2*3], mpDropdownUVCoords_active[2*3+1] ); mpDropdownIdleSizeList[3].width = middleWidth; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 4*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle, (float)mControlDimensions.y+mSmallestTopSizeIdle, (float) middleWidth, (float) middleHeight, mpDropdownUVCoords_active[2*4], mpDropdownUVCoords_active[2*4+1] ); mpDropdownIdleSizeList[4].width = middleWidth; mpDropdownIdleSizeList[4].height = middleHeight; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 5*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle, (float)mControlDimensions.y+mSmallestTopSizeIdle+middleHeight, (float) middleWidth, (float) mpDropdownIdleImageSizeList[5].height, mpDropdownUVCoords_active[2*5], mpDropdownUVCoords_active[2*5+1] ); mpDropdownIdleSizeList[5].width = middleWidth; // right AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 6*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle+middleWidth, (float)mControlDimensions.y, (float) mpDropdownIdleImageSizeList[6].width, (float)mpDropdownIdleImageSizeList[6].height, mpDropdownUVCoords_active[2*6], mpDropdownUVCoords_active[2*6+1] ); AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 7*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle+middleWidth, (float)mControlDimensions.y+mSmallestTopSizeIdle, (float) mpDropdownIdleImageSizeList[7].width, (float)middleHeight, mpDropdownUVCoords_active[2*7], mpDropdownUVCoords_active[2*7+1] ); mpDropdownIdleSizeList[7].height = middleHeight; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 8*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle+middleWidth, (float)mControlDimensions.y+mSmallestTopSizeIdle+middleHeight, (float) mpDropdownIdleImageSizeList[8].width, (float)mpDropdownIdleImageSizeList[8].height, mpDropdownUVCoords_active[2*8], mpDropdownUVCoords_active[2*8+1] ); // 2 buttons (up and pressed) at same location CPUT_RECT rect; CalculateButtonRect(rect); AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 9*6, (float)rect.x, (float)rect.y, (float) mpDropdownIdleImageSizeList[ 9].width, (float)mpDropdownIdleImageSizeList[ 9].height, mpDropdownUVCoords_active[2*9], mpDropdownUVCoords_active[2*9+1] ); AddQuadIntoMirrorBuffer(mpMirrorBufferActive, 10*6, (float)rect.x, (float)rect.y, (float) mpDropdownIdleImageSizeList[10].width, (float)mpDropdownIdleImageSizeList[10].height, mpDropdownUVCoords_active[2*10], mpDropdownUVCoords_active[2*10+1] ); // if the dropdown tray is active, draw it int index=11; if(CPUT_CONTROL_ACTIVE == mControlState) { if((CPUT_DROPDOWN_GUI_MOUSE_PRESSED == mControlGuiState) && (0 != mpListOfSelectableItems.size())) { CalculateTrayRect(inner, outer); mTrayDimensions.width = inner.width; mTrayDimensions.height = inner.height; float tx, ty; tx = (float)outer.x; ty = (float)outer.y; int numberOfItemsInList = (int) mpListOfSelectableItems.size(); CalculateMaxItemSize(mTrayDimensions.width, mTrayDimensions.height); mTrayDimensions.width += 2*CPUT_DROPDOWN_TEXT_PADDING; mTrayDimensions.height = inner.height; // ( numberOfItemsInList * (mTrayDimensions.height+CPUT_DROPDOWN_TEXT_PADDING)); // lm AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)tx, (float)ty, (float) mpDropdownIdleImageSizeList[CTrayLM].width, (float)mTrayDimensions.height, mpDropdownUVCoords_active[2*CTrayLM], mpDropdownUVCoords_active[2*CTrayLM+1] ); index++; // lb ty+=mTrayDimensions.height; // inner.height AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)tx, (float)ty, (float) mpDropdownIdleImageSizeList[CTrayLB].width, (float)mpDropdownIdleImageSizeList[CTrayLB].height, mpDropdownUVCoords_active[2*CTrayLB], mpDropdownUVCoords_active[2*CTrayLB+1] ); index++; // mm tx+=mpDropdownIdleImageSizeList[CLeftMid].width; ty = (float)outer.y; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)tx, (float)ty, (float) mTrayDimensions.width, (float)mTrayDimensions.height, mpDropdownUVCoords_active[2*CTrayMM], mpDropdownUVCoords_active[2*CTrayMM+1] ); index++; // mb ty+=mTrayDimensions.height; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)tx, (float)ty, (float) mTrayDimensions.width, (float)mpDropdownIdleImageSizeList[CTrayMB].height, mpDropdownUVCoords_active[2*CTrayMB], mpDropdownUVCoords_active[2*CTrayMB+1] ); index++; // rm tx+=mTrayDimensions.width; ty = (float)outer.y; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)tx, (float)ty, (float) mpDropdownIdleImageSizeList[CTrayRM].width, (float)mTrayDimensions.height, mpDropdownUVCoords_active[2*CTrayRM], mpDropdownUVCoords_active[2*CTrayRM+1] ); index++; // rb ty += mTrayDimensions.height; AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)tx, (float)ty, (float) mpDropdownIdleImageSizeList[CTrayRB].width, (float)mpDropdownIdleImageSizeList[CTrayRB].height, mpDropdownUVCoords_active[2*CTrayRB], mpDropdownUVCoords_active[2*CTrayRB+1] ); index++; // tray highlight int MaxSizeItemWidth, MaxSizeItemHeight; CalculateMaxItemSize(MaxSizeItemWidth, MaxSizeItemHeight); int sx = (inner.x + mpDropdownIdleImageSizeList[CLeftMid].width); int sy = (inner.y + CPUT_DROPDOWN_TEXT_PADDING); for(UINT i=0;i<mpListOfSelectableItems.size();i++) { if( (mSelectedItemIndex) == i ) { //m = XMMatrixTranslation((float)(sx - CPUT_DROPDOWN_TEXT_PADDING), (float)(sy - CPUT_DROPDOWN_TEXT_PADDING), 0); AddQuadIntoMirrorBuffer(mpMirrorBufferActive, index*6, (float)(sx - CPUT_DROPDOWN_TEXT_PADDING), (float)(sy - CPUT_DROPDOWN_TEXT_PADDING), (float) MaxSizeItemWidth + 2*CPUT_DROPDOWN_TEXT_PADDING, (float)MaxSizeItemHeight + CPUT_DROPDOWN_TEXT_PADDING, mpDropdownUVCoords_active[2*CTrayHighlight], mpDropdownUVCoords_active[2*CTrayHighlight+1] ); index++; } CPUT_RECT rect; mpListOfSelectableItems[i]->GetDimensions(rect.width, rect.height); sy+=rect.height + 2*CPUT_DROPDOWN_TEXT_PADDING; } } } // calculate the disabled item list // left AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 0*6, (float)mControlDimensions.x, (float)mControlDimensions.y, (float) mpDropdownIdleImageSizeList[0].width, (float) mpDropdownIdleImageSizeList[0].height, mpDropdownUVCoords_disabled[2*0], mpDropdownUVCoords_disabled[2*0+1] ); AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 1*6, (float)mControlDimensions.x, (float)mControlDimensions.y+mSmallestTopSizeIdle, (float) mpDropdownIdleImageSizeList[1].width, (float) middleHeight, mpDropdownUVCoords_disabled[2*1], mpDropdownUVCoords_disabled[2*1+1] ); mpDropdownIdleSizeList[1].height = middleHeight; AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 2*6, (float)mControlDimensions.x, (float)mControlDimensions.y+mSmallestTopSizeIdle+middleHeight, (float) mpDropdownIdleImageSizeList[2].width, (float) mpDropdownIdleImageSizeList[2].height, mpDropdownUVCoords_disabled[2*2], mpDropdownUVCoords_disabled[2*2+1] ); // middle AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 3*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle, (float)mControlDimensions.y, (float) middleWidth, (float) mpDropdownIdleImageSizeList[3].height, mpDropdownUVCoords_disabled[2*3], mpDropdownUVCoords_disabled[2*3+1] ); mpDropdownIdleSizeList[3].width = middleWidth; AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 4*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle, (float)mControlDimensions.y+mSmallestTopSizeIdle, (float) middleWidth, (float) middleHeight, mpDropdownUVCoords_disabled[2*4], mpDropdownUVCoords_disabled[2*4+1] ); mpDropdownIdleSizeList[4].width = middleWidth; mpDropdownIdleSizeList[4].height = middleHeight; AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 5*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle, (float)mControlDimensions.y+mSmallestTopSizeIdle+middleHeight, (float) middleWidth, (float) mpDropdownIdleImageSizeList[5].height, mpDropdownUVCoords_disabled[2*5], mpDropdownUVCoords_disabled[2*5+1] ); mpDropdownIdleSizeList[5].width = middleWidth; // right AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 6*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle+middleWidth, (float)mControlDimensions.y, (float) mpDropdownIdleImageSizeList[6].width, (float)mpDropdownIdleImageSizeList[6].height, mpDropdownUVCoords_disabled[2*6], mpDropdownUVCoords_disabled[2*6+1] ); AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 7*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle+middleWidth, (float)mControlDimensions.y+mSmallestTopSizeIdle, (float) mpDropdownIdleImageSizeList[7].width, (float)middleHeight, mpDropdownUVCoords_disabled[2*7], mpDropdownUVCoords_disabled[2*7+1] ); mpDropdownIdleSizeList[7].height = middleHeight; AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 8*6, (float)mControlDimensions.x+mSmallestLeftSizeIdle+middleWidth, (float)mControlDimensions.y+mSmallestTopSizeIdle+middleHeight, (float) mpDropdownIdleImageSizeList[8].width, (float)mpDropdownIdleImageSizeList[8].height, mpDropdownUVCoords_disabled[2*8], mpDropdownUVCoords_disabled[2*8+1] ); // 2 buttons (up and pressed) at same location CalculateButtonRect(rect); AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 9*6, (float)rect.x, (float)rect.y, (float) mpDropdownIdleImageSizeList[ 9].width, (float)mpDropdownIdleImageSizeList[ 9].height, mpDropdownUVCoords_disabled[2*9], mpDropdownUVCoords_disabled[2*9+1] ); AddQuadIntoMirrorBuffer(mpMirrorBufferDisabled, 10*6, (float)rect.x, (float)rect.y, (float) mpDropdownIdleImageSizeList[10].width, (float)mpDropdownIdleImageSizeList[10].height, mpDropdownUVCoords_disabled[2*10], mpDropdownUVCoords_disabled[2*10+1] ); // -- now handle the text -- // draw the selected item in the readout display if(-1!=mSelectedItemIndex) { int x,y; CalculateReadoutTextPosition(x,y); cString string; mpListOfSelectableItems[mSelectedItemIndex]->GetString(string); mpSelectedItemCopy->SetText(string); mpSelectedItemCopy->SetPosition(x,y); mpListOfSelectableItems[mSelectedItemIndex]->SetPosition(x,y); } // calculate each of the individual dropdown text string locations CalculateTrayRect(inner, outer); float tx, ty; tx = (float)outer.x; ty = (float)outer.y; int sx = (inner.x + mpDropdownIdleImageSizeList[CLeftMid].width); int sy = (inner.y + CPUT_DROPDOWN_TEXT_PADDING); for(UINT i=0;i<mpListOfSelectableItems.size();i++) { mpListOfSelectableItems[i]->SetPosition(sx, sy); CPUT_RECT rect; mpListOfSelectableItems[i]->GetDimensions(rect.width, rect.height); sy+=rect.height + 2*CPUT_DROPDOWN_TEXT_PADDING; } // mark this as dirty CPUTGuiControllerDX11::GetController()->ControlIsDirty(); }
// Handle mouse events //----------------------------------------------------------------------------- CPUTEventHandledCode CPUTDropdown::HandleMouseEvent(int x, int y, int wheel, CPUTMouseState state) { UNREFERENCED_PARAMETER(wheel); CPUTEventHandledCode handledCode = CPUT_EVENT_UNHANDLED; // just return if the control is disabled or invisible if((CPUT_CONTROL_INACTIVE == mControlState) || (false == mControlVisible) ) { mbMouseInside = false; return handledCode; } // tray is down, commence to selecting if(CPUT_DROPDOWN_GUI_MOUSE_PRESSED == mControlGuiState) { if(ContainsPointTrayArea(x, y)) { // tray is open // float the selection up/down based on mouse position, making // whichever item the mouse is over the selected item CPUT_RECT inner, outer; CalculateTrayRect(inner, outer); if( (x>outer.x) && (x<outer.x+outer.width) && (y>inner.y) && (y<inner.y+inner.height)) { // figure out which one was selected int itemWidth, itemHeight; CalculateMaxItemSize(itemWidth, itemHeight); int itemSelect = (int)( (y - inner.y) / (float)(itemHeight+2*CPUT_DROPDOWN_TEXT_PADDING)); SetSelectedItem(itemSelect+1); } if( CPUT_MOUSE_LEFT_DOWN == state ) { mbStartedClickInsideTray = true; } // released the left-down button, but there was a click started here if( !(CPUT_MOUSE_LEFT_DOWN == state) && (true == mbStartedClickInsideTray) ) { // mark click start as no longer active mbStartedClickInsideTray = false; // close the tray //mControlState = CPUT_CONTROL_ACTIVE; mControlGuiState = CPUT_DROPDOWN_GUI_MOUSE_NEUTRAL; Recalculate(); // fire callback mpCallbackHandler->HandleCallbackEvent(1, mcontrolID, (CPUTControl*) this); // remember this item as the last selected item GetSelectedItem(mRevertItem); } // anything in the tray counts as handling the mouse event return CPUT_EVENT_HANDLED; } } // handle just the readout area if(ContainsPointReadoutArea(x,y)) { // click started outside this control - ignore it if( (false == mbMouseInside ) && (CPUT_MOUSE_LEFT_DOWN == state) ) { return handledCode; } // clicked and dragging around inside the control itself - ignore if( (true == mbStartedClickInside ) && (CPUT_MOUSE_LEFT_DOWN == state) ) { return CPUT_EVENT_HANDLED; } mbMouseInside = true; if( !(CPUT_MOUSE_LEFT_DOWN == state)) { mbStartedClickInside = false; mbStartedClickInsideTray = false; } if( CPUT_MOUSE_LEFT_DOWN == state ) { if(CPUT_DROPDOWN_GUI_MOUSE_NEUTRAL == mControlGuiState) { mbStartedClickInside = true; mbStartedClickInsideTray = true; // get the item to revert to GetSelectedItem(mRevertItem); // toggle tray state mControlGuiState = CPUT_DROPDOWN_GUI_MOUSE_PRESSED; Recalculate(); } else { mbStartedClickInside = true; mbStartedClickInsideTray = true; //mControlState = CPUT_CONTROL_ACTIVE; mControlGuiState = CPUT_DROPDOWN_GUI_MOUSE_NEUTRAL; SetSelectedItem(mRevertItem); mRevertItem=(UINT)-1; Recalculate(); } return CPUT_EVENT_HANDLED; } } else if(CPUT_MOUSE_LEFT_DOWN == state) { // clicked outside the control // if tray is down, restore previous selection and disable // display of the tray if(CPUT_DROPDOWN_GUI_MOUSE_NEUTRAL != mControlGuiState) { mControlGuiState = CPUT_DROPDOWN_GUI_MOUSE_NEUTRAL; SetSelectedItem(mRevertItem); mRevertItem=(UINT)-1; Recalculate(); } mbStartedClickInside = false; mbMouseInside = false; return CPUT_EVENT_UNHANDLED; } return handledCode; }