#ifndef __DROPDOWN_H #define __DROPDOWN_H /** * @file * @author Flugente (bears-pit.com) */ #include "LaptopSave.h" /* * helpful draw functions that used to draw the boundaries of the dropdown. The old way of adding sti objects to paint boundaries is... lets say, inefficient */ void DisplaySmallLine( UINT16 usStartX, UINT16 usStartY, UINT16 EndX, UINT16 EndY, UINT16 usColor ); void Display2Line2ShadowVertical( UINT16 usStartX, UINT16 usStartY, UINT16 EndX, UINT16 usColor1, UINT16 usColor2 ); void Display2Line2ShadowHorizontal( UINT16 usStartX, UINT16 usStartY, UINT16 EndY, UINT16 usColor1, UINT16 usColor2 ); /* * A simple class that takes coordinates and colors. * It simply exists to provide these simple methods for other classes. */ class WidgetBase { public: WidgetBase( ); /* * X and Y-Coordinates define the upper left corner */ void SetX( UINT16 aVal ) { musStartX = aVal; } virtual UINT16 GetX( ) { return musStartX; } void SetY( UINT16 aVal ) { musStartY = aVal; } virtual UINT16 GetY( ) { return musStartY; } /* * X and Y-Coordinates for text */ void SetX_Text( UINT16 aVal ) { musStartX_Text = aVal; } virtual UINT16 GetX_Text( ) { return musStartX_Text; } void SetY_Text( UINT16 aVal ) { musStartY_Text = aVal; } virtual UINT16 GetY_Text( ) { return musStartY_Text; } /* * Color of boundary line */ void SetColorLine( UINT16 aCol ) { mColorLine = aCol; } UINT16 GetColorLine( ) { return mColorLine; } /* * Color of boundary line shadow */ void SetColorLineShadow( UINT16 aCol ) { mColorLineShadow = aCol; } UINT16 GetColorLineShadow( ) { return mColorLineShadow; } /* * background color of selected entry */ void SetColorMarked( UINT16 aCol ) { mColorMarked = aCol; } UINT16 GetColorMarked( ) { return mColorMarked; } /* * Color of highlighted element */ void SetColorHighLight( UINT16 aCol ) { mColorHighLight = aCol; } UINT16 GetColorHighLight( ) { return mColorHighLight; } private: // declare but don't define WidgetBase( WidgetBase const& ); void operator=(WidgetBase const&); private: UINT16 musStartX; UINT16 musStartY; UINT16 musStartX_Text; UINT16 musStartY_Text; UINT16 mColorLine; // color of boundary lines UINT16 mColorLineShadow; // color of boundary line shadows UINT16 mColorMarked; // color of marked entries UINT16 mColorHighLight; // color of bar highlighting }; // the maximum number of entries that can be shown at once. Increase requires recompilation! #define DROPDOWN_REGIONS 8 // different dropdowns can interfere with each other enum definedDropDowns { DROPDOWNNR_APPEARANCE = 0, DROPDOWNNR_APPEARANCECARE, DROPDOWNNR_REFINEMENT, DROPDOWNNR_REFINEMENTCARE, DROPDOWNNR_NATIONALITY, DROPDOWNNR_HATEDNATIONALITY, DROPDOWNNR_HATEDNATIONALITYCARE, DROPDOWNNR_RACIST, DROPDOWNNR_RACE, DROPDOWNNR_SEXIST, DROPDOWNNR_RACISTFEATURE, DROPDOWNNR_MERCCOMPARE1, DROPDOWNNR_MERCCOMPARE2, DROPDOWNNR_MERCCOMPARE_SQUADSELECTION, DROPDOWNNR_PERSONALITY, DROPDOWNNR_PMC_LOCATION, DROPDOWNNR_IMPGEAR_LBE1, DROPDOWNNR_IMPGEAR_LBE2, DROPDOWNNR_IMPGEAR_LBE3, DROPDOWNNR_IMPGEAR_LBE4, DROPDOWNNR_IMPGEAR_LBE5, DROPDOWNNR_IMPGEAR_GUN_1, DROPDOWNNR_IMPGEAR_AMMO_1, DROPDOWNNR_IMPGEAR_GUN_2, DROPDOWNNR_IMPGEAR_AMMO_2, DROPDOWNNR_IMPGEAR_MELEE, DROPDOWNNR_IMPGEAR_HELMET, DROPDOWNNR_IMPGEAR_VEST, DROPDOWNNR_IMPGEAR_LEGS, DROPDOWNNR_IMPGEAR_FACE1, DROPDOWNNR_IMPGEAR_FACE2, DROPDOWNNR_IMPGEAR_MISC_1, DROPDOWNNR_IMPGEAR_MISC_2, DROPDOWNNR_IMPGEAR_MISC_3, DROPDOWNNR_IMPGEAR_MISC_4, DROPDOWNNR_IMPGEAR_MISC_5, DROPDOWNNR_IMPGEAR_MISC_6, DROPDOWNNR_IMPGEAR_MISC_7, DROPDOWNNR_IMPGEAR_MAX = DROPDOWNNR_IMPGEAR_MISC_7, DROPDOWNNR_MSGBOX_1, DROPDOWNNR_MSGBOX_2, DROPDOWN_INTEL_BUY, DROPDOWN_MILTIAWEBSITE_FILTER_DEAD, DROPDOWN_MILTIAWEBSITE_FILTER_RANK, DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN, DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR, DROPDOWN_REBEL_COMMAND_DIRECTIVE, }; /* * As we cannot directly add our callbacks (we need a static callback due to the way MSYS_DefineRegion(...) works, which utterly fails if we have multiple instance of a class), * we use a very odd looking workaround. * We do not directly use DropDownBase. Instead we use DropDownTemplate, which is a template taking an int N. This template is a singleton. This means that for each N, there can only be one * instance of the class. This is necessary as we internally need a unique static self-pointer. * If you try to have two instances on the same screen, only one will show, which will be confusing. So simply use a separate N fore each instance. See IMP Prejudice.cpp to get an idea of how that is done. * * Apart from that, you will only have to implement void SetRefresh(). This function is necessary to refresh the screen after the popup-section is closed, otherwise it will still be shown. * * As this class refreshes itself once you have properly implemented SetRefresh(), you can even move the box around onscreen, it will properly refresh, so moving it with a mouse will be possible * * You can get an instance by calling DropDownTemplate.Create(UINT16 usX, UINT16 usY);, the constructor itself is private (singleton). Usage: std::vector > entryvecDropDown_Appearance; for(UINT8 i = 0; i < NUM_APPEARANCES; ++i) entryvecDropDown_Appearance.push_back( std::make_pair(i, szAppearanceText[i]) ); DropDownTemplate.SetEntries(entryvecDropDown_Appearance); DropDownTemplate.Create(usX, usY); ... */ class DropDownBase : public WidgetBase { public: DropDownBase(); /* * Create a Dropdown with upper left coordinates */ void Create(UINT16 sX, UINT16 sY); /* * Destroy Dropdown, for example once a website isn't displayed anymore */ void Destroy(); /* * Display DropDownBase. Use this when refreshing */ void Display(); /* * Sometimes a refresh inside the class isn't enough - best example is closing the dropdown area, after which the previous background cannot be restored by this class. * In that case, the background and this class has to be redrawn. * This function is called internally whenever such a refresh is necessary. * It has to be defined in derived classes and should notify your dialogues to redraw at appropriate times * * This function has to be implemented! */ virtual void SetRefresh() = 0; // internal callback types enum { DROPDOWN_OPEN = 0, DROPDOWN_CLOSE, DROPDOWN_REGION, DROPDOWN_MOVEMENT, DROPDOWN_ARROW, DROPDOWN_SCROLL_REGION, DROPDOWN_SCROLL_MOVEMENT, }; /* * Set the content of a dropdown. Each entry consists of an INT16 key, by which you can later identify which entry was selected, and a STR16 that will be displayed. * There can be multiple instances of the same key or name. */ void SetEntries( std::vector >& arEntryVec ) { mEntryVector = arEntryVec; mNumDisplayedEntries = min( DROPDOWN_REGIONS, mEntryVector.size( ) ); } /* * Set help text decribing what can be selected */ void SetHelpText( STR16 aText ) { swprintf( mHelpText, L"" ); wcscat( mHelpText, aText ); } /* * Get key of selected entry */ INT16 GetSelectedEntryKey() { if ( mEntryVector.empty() ) return -1; return mEntryVector[mSelectedEntry].first; } /* * If aKey exists among our keys, set it as the current one */ void SetSelectedEntryKey( INT16 aKey ); /* * set the nth entry as the selected one */ void SetNthEntry( UINT16 aNr ); /* * Get width of entire DropDownBase */ UINT16 GetTotalWidth() { return musWidth + musArrowWidth; } /* * Get right x coordinate */ UINT16 GetLastX() { return GetX() + GetTotalWidth(); } /* * Are we displayed? */ BOOLEAN IsDisplayed() { return mfMouseRegionsCreated; } /* * Do we have data to display? */ BOOLEAN HasEntries( ) { return !mEntryVector.empty(); } /* * Remove all entries */ void ClearEntries( ) { mSelectedEntry = 0; mEntryVector.clear( ); } // call to open/close the drop down void OpenDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void CloseDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void SelectDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void SelectDropDownMovementCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void SelectUpDownArrowOnScrollAreaRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void SelectScrollAreaDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void SelectScrollAreaDropDownMovementCallBack(MOUSE_REGION * pRegion, INT32 iReason ); /* * This function is implemented again in DropDownTemplate */ virtual MOUSE_CALLBACK CallBackWrapper(void* pt2Object, UINT8 arg, void (*pt2Function)(MOUSE_REGION * pRegion, INT32 iReason) ) { return Dummyfunc; } private: // declare but don't define DropDownBase(DropDownBase const&); void operator=(DropDownBase const&); /* * Initialise variables. Called after each creationm which allows moving a dropdown */ void Init(UINT16 sX, UINT16 sY); /* * Functions exclusively for the dropdown region, which is only shown after user interaction */ void Create_Drop(); void Init_Drop(); void Display_Drop(); void Destroy_Drop(); /* * This dummy is needed internally and does nothing when called */ static void Dummyfunc(MOUSE_REGION * pRegion, INT32 iReason ) {} void DrawTopEntry(); void DrawSelectedCity(); void DrawGoldRectangle(); private: UINT16 musHeight; UINT16 musWidth; UINT16 musStartX_Drop; UINT16 musStartY_Drop; UINT16 musScrollAreaX; UINT16 musUpArrowX; UINT16 musUpArrowY; UINT16 musDownArrowX; UINT16 musDownArrowY; UINT16 musArrowWidth; UINT16 musAreaHeight; UINT16 musFontHeight; BOOLEAN mfMouseRegionsCreated; BOOLEAN mfMouseRegionsCreated_Drop; MOUSE_REGION mSelectedOpenDropDownRegion; MOUSE_REGION mSelectedCloseDropDownRegion; MOUSE_REGION mBubbleHelpRegion; // for a help text describing what a selection is good for, can be seen when hovering the mouse over the box when it is closed MOUSE_REGION mDropDownRegion[DROPDOWN_REGIONS]; MOUSE_REGION mgSelectedUpDownArrowOnScrollAreaRegion[2]; MOUSE_REGION mSelectedScrollAreaDropDownRegion[DROPDOWN_REGIONS]; std::vector > mEntryVector; CHAR16 mHelpText[200]; UINT16 mSelectedEntry; // keeps track of the currently selected city UINT16 mFirstShownEntry; // top entry of the dropped region UINT16 mNumDisplayedEntries; // number of entries displayed. Calculated internally, no need to change by user BOOLEAN mfDropScrollBar; // do we need a scrollbar and a down arrow? }; template class DropDownTemplate : public DropDownBase { public: static DropDownTemplate& getInstance() { static DropDownTemplate instance; // Guaranteed to be destroyed. // Instantiated on first use. return instance; } // this function has to be implemented! virtual void SetRefresh(); static void OpenDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->OpenDropDownRegionCallBack(pRegion, iReason); } static void CloseDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->CloseDropDownRegionCallBack(pRegion, iReason); } static void SelectRegionDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->SelectDropDownRegionCallBack(pRegion, iReason); } static void SelectMovementDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->SelectDropDownMovementCallBack(pRegion, iReason); } static void SelectArrowDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->SelectUpDownArrowOnScrollAreaRegionCallBack(pRegion, iReason); } static void SelectScrollRegionDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->SelectScrollAreaDropDownRegionCallBack(pRegion, iReason); } static void SelectScrollMovementDropDown_DropDown(MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast(mpSelf)->SelectScrollAreaDropDownMovementCallBack(pRegion, iReason); } MOUSE_CALLBACK CallBackWrapper(void* pt2Object, UINT8 arg, void (*pt2Function)(MOUSE_REGION * pRegion, INT32 iReason) ) { mpSelf = pt2Object; switch ( arg ) { case DROPDOWN_OPEN: return &OpenDropDown_DropDown; break; case DROPDOWN_CLOSE: return &CloseDropDown_DropDown; break; case DROPDOWN_REGION: return &SelectRegionDropDown_DropDown; break; case DROPDOWN_MOVEMENT: return &SelectMovementDropDown_DropDown; break; case DROPDOWN_ARROW: return &SelectArrowDropDown_DropDown; break; case DROPDOWN_SCROLL_REGION: return &SelectScrollRegionDropDown_DropDown; break; case DROPDOWN_SCROLL_MOVEMENT: return &SelectScrollMovementDropDown_DropDown; break; } return *pt2Function; } private: static void* mpSelf; private: DropDownTemplate() {}; // private constructor, so we cannot create more instances // declare but don't define DropDownTemplate(DropDownTemplate const&); void operator=(DropDownTemplate const&); }; template void DropDownTemplate::SetRefresh(); template void* DropDownTemplate::mpSelf = NULL; #endif