tron@2186: /* $Id$ */ tron@2186: belugas@6443: /** @file window.h regroups declarations for all windowing system, as well as a few helper functions */ belugas@6443: truelight@0: #ifndef WINDOW_H truelight@0: #define WINDOW_H truelight@0: belugas@4692: #include "macros.h" truelight@4299: #include "string.h" bjarni@4712: #include "order.h" rubidium@5838: #include "rail.h" rubidium@7162: #include "road.h" rubidium@5838: #include "airport.h" rubidium@7134: #include "vehicle.h" rubidium@8384: #include "viewport.h" truelight@4299: rubidium@6574: struct WindowEvent; truelight@0: truelight@0: typedef void WindowProc(Window *w, WindowEvent *e); truelight@0: truelight@867: /* How the resize system works: truelight@867: First, you need to add a WWT_RESIZEBOX to the widgets, and you need truelight@867: to add the flag WDF_RESIZABLE to the window. Now the window is ready truelight@867: to resize itself. truelight@867: As you may have noticed, all widgets have a RESIZE_XXX in their line. truelight@867: This lines controls how the widgets behave on resize. RESIZE_NONE means truelight@867: it doesn't do anything. Any other option let's one of the borders truelight@867: move with the changed width/height. So if a widget has truelight@867: RESIZE_RIGHT, and the window is made 5 pixels wider by the user, truelight@867: the right of the window will also be made 5 pixels wider. truelight@867: Now, what if you want to clamp a widget to the bottom? Give it the flag truelight@867: RESIZE_TB. This is RESIZE_TOP + RESIZE_BOTTOM. Now if the window gets truelight@867: 5 pixels bigger, both the top and bottom gets 5 bigger, so the whole truelight@867: widgets moves downwards without resizing, and appears to be clamped truelight@867: to the bottom. Nice aint it? truelight@867: You should know one more thing about this system. Most windows can't truelight@867: handle an increase of 1 pixel. So there is a step function, which truelight@867: let the windowsize only be changed by X pixels. You configure this truelight@867: after making the window, like this: truelight@867: w->resize.step_height = 10; truelight@867: Now the window will only change in height in steps of 10. truelight@867: You can also give a minimum width and height. The default value is truelight@867: the default height/width of the window itself. You can change this truelight@867: AFTER window-creation, with: truelight@867: w->resize.width or w->resize.height. truelight@867: That was all.. good luck, and enjoy :) -- TrueLight */ truelight@867: rubidium@6574: enum ResizeFlag { belugas@6505: RESIZE_NONE = 0, ///< no resize required truelight@867: belugas@6505: RESIZE_LEFT = 1, ///< left resize flag belugas@6505: RESIZE_RIGHT = 2, ///< rigth resize flag belugas@6505: RESIZE_TOP = 4, ///< top resize flag belugas@6505: RESIZE_BOTTOM = 8, ///< bottom resize flag truelight@867: belugas@6505: RESIZE_LR = RESIZE_LEFT | RESIZE_RIGHT, ///< combination of left and right resize flags belugas@6505: RESIZE_RB = RESIZE_RIGHT | RESIZE_BOTTOM, ///< combination of right and bottom resize flags belugas@6505: RESIZE_TB = RESIZE_TOP | RESIZE_BOTTOM, ///< combination of top and bottom resize flags belugas@6505: RESIZE_LRB = RESIZE_LEFT | RESIZE_RIGHT | RESIZE_BOTTOM, ///< combination of left, right and bottom resize flags belugas@6505: RESIZE_LRTB = RESIZE_LEFT | RESIZE_RIGHT | RESIZE_TOP | RESIZE_BOTTOM, ///< combination of all resize flags belugas@6505: RESIZE_RTB = RESIZE_RIGHT | RESIZE_TOP | RESIZE_BOTTOM, ///< combination of right, top and bottom resize flag belugas@4749: belugas@4749: /* The following flags are used by the system to specify what is disabled, hidden, or clicked belugas@4749: * They are used in the same place as the above RESIZE_x flags, Widget visual_flags. belugas@4749: * These states are used in exceptions. If nothing is specified, they will indicate belugas@4749: * Enabled, visible or unclicked widgets*/ belugas@6443: WIDG_DISABLED = 4, ///< widget is greyed out, not available belugas@6443: WIDG_HIDDEN = 5, ///< widget is made invisible belugas@6443: WIDG_LOWERED = 6, ///< widget is paint lowered, a pressed button in fact rubidium@6574: }; truelight@867: glx@4755: enum { belugas@6505: WIDGET_LIST_END = -1, ///< indicate the end of widgets' list for vararg functions glx@4755: }; glx@4755: rubidium@6574: struct Widget { belugas@6443: byte type; ///< Widget type, see WindowWidgetTypes belugas@6443: byte display_flags; ///< Resize direction, alignment, etc. during resizing, see ResizeFlags Darkvater@4547: byte color; ///< Widget colour, see docs/ottd-colourtext-palette.png bjarni@6224: int16 left, right, top, bottom; ///< The position offsets inside the window Darkvater@4547: uint16 data; ///< The String/Image or special code (list-matrixes) of a widget Darkvater@4547: StringID tooltips; ///< Tooltips that are shown when rightclicking on a widget rubidium@6574: }; truelight@0: rubidium@6574: enum FrameFlags { rubidium@5838: FR_NONE = 0x00, hackykid@1938: FR_TRANSPARENT = 0x01, ///< Makes the background transparent if set hackykid@1938: FR_BORDERONLY = 0x10, ///< Draw border only, no background hackykid@1938: FR_LOWERED = 0x20, ///< If set the frame is lowered and the background color brighter (ie. buttons when pressed) hackykid@1938: FR_DARKENED = 0x40, ///< If set the background is darker, allows for lowered frames with normal background color when used with FR_LOWERED (ie. dropdown boxes) rubidium@6574: }; tron@4437: rubidium@5838: DECLARE_ENUM_AS_BIT_SET(FrameFlags); rubidium@5838: tron@4437: void DrawFrameRect(int left, int top, int right, int bottom, int color, FrameFlags flags); hackykid@1938: belugas@4634: enum WindowEventCodes { Darkvater@5664: WE_CREATE, Darkvater@5664: WE_DESTROY, Darkvater@5664: WE_PAINT, Darkvater@5664: WE_KEYPRESS, Darkvater@5664: WE_CLICK, truelight@7505: WE_DOUBLE_CLICK, Darkvater@5664: WE_RCLICK, Darkvater@5664: WE_MOUSEOVER, Darkvater@5664: WE_MOUSELOOP, Darkvater@5664: WE_MOUSEWHEEL, Darkvater@5664: WE_TICK, Darkvater@5664: WE_4, Darkvater@5664: WE_TIMEOUT, Darkvater@5664: WE_PLACE_OBJ, Darkvater@5664: WE_ABORT_PLACE_OBJ, Darkvater@5664: WE_ON_EDIT_TEXT, Darkvater@5664: WE_ON_EDIT_TEXT_CANCEL, Darkvater@5664: WE_POPUPMENU_SELECT, Darkvater@5664: WE_POPUPMENU_OVER, Darkvater@5664: WE_DRAGDROP, Darkvater@5664: WE_PLACE_DRAG, Darkvater@5664: WE_PLACE_MOUSEUP, Darkvater@5664: WE_PLACE_PRESIZE, Darkvater@5664: WE_DROPDOWN_SELECT, Darkvater@5664: WE_RESIZE, Darkvater@5664: WE_MESSAGE, Darkvater@5664: WE_SCROLL, Darkvater@5664: WE_INVALIDATE_DATA, belugas@4634: }; truelight@0: belugas@4634: struct WindowEvent { belugas@4634: byte event; belugas@4634: union { rubidium@7863: struct { rubidium@7863: void *data; rubidium@7863: } create; rubidium@7863: rubidium@7863: struct { belugas@4634: Point pt; belugas@4634: int widget; belugas@4634: } click; truelight@543: belugas@4634: struct { belugas@4634: Point pt; belugas@4634: TileIndex tile; belugas@4634: TileIndex starttile; rubidium@8384: ViewportPlaceMethod select_method; maedhros@7165: byte select_proc; belugas@4634: } place; darkvater@1648: belugas@4634: struct { belugas@4634: Point pt; belugas@4634: int widget; belugas@4634: } dragdrop; truelight@4335: belugas@4634: struct { belugas@4634: Point size; belugas@4634: Point diff; belugas@4634: } sizing; truelight@4337: belugas@4634: struct { belugas@4634: char *str; belugas@4634: } edittext; belugas@4634: belugas@4634: struct { belugas@4634: Point pt; belugas@4634: } popupmenu; belugas@4634: belugas@4634: struct { belugas@4634: int button; belugas@4634: int index; belugas@4634: } dropdown; belugas@4634: belugas@4634: struct { belugas@4634: Point pt; belugas@4634: int widget; belugas@4634: } mouseover; belugas@4634: belugas@4634: struct { belugas@6443: bool cont; ///< continue the search? (default true) belugas@6443: uint16 key; ///< 16-bit Unicode value of the key belugas@6443: uint16 keycode; ///< untranslated key (including shift-state) belugas@4634: } keypress; belugas@4634: belugas@4634: struct { belugas@6443: int msg; ///< message to be sent belugas@6443: int wparam; ///< additional message-specific information belugas@6443: int lparam; ///< additional message-specific information belugas@4634: } message; belugas@4634: belugas@4634: struct { belugas@6443: Point delta; ///< delta position against position of last call belugas@4634: } scroll; belugas@4634: belugas@4634: struct { belugas@6443: int wheel; ///< how much was 'wheel'd' belugas@4634: } wheel; belugas@4634: } we; truelight@0: }; truelight@0: rubidium@6574: struct WindowDesc { rubidium@7837: int16 left, top, minimum_width, minimum_height, default_width, default_height; tron@2788: WindowClass cls; tron@2788: WindowClass parent_cls; truelight@0: uint32 flags; truelight@0: const Widget *widgets; truelight@0: WindowProc *proc; rubidium@6574: }; truelight@0: Darkvater@5664: enum WindowDefaultFlag { belugas@6443: WDF_STD_TOOLTIPS = 1, ///< use standard routine when displaying tooltips belugas@6443: WDF_DEF_WIDGET = 2, ///< default widget control for some widgets in the on click event belugas@6443: WDF_STD_BTN = 4, ///< default handling for close and drag widgets (widget no 0 and 1) ludde@2064: belugas@6443: WDF_UNCLICK_BUTTONS = 16, ///< Unclick buttons when the window event times out */ belugas@6443: WDF_STICKY_BUTTON = 32, ///< Set window to sticky mode; they are not closed unless closed with 'X' (widget 2) belugas@6443: WDF_RESIZABLE = 64, ///< A window can be resized belugas@6443: WDF_MODAL = 128, ///< The window is a modal child of some other window, meaning the parent is 'inactive' truelight@0: }; truelight@0: truelight@0: /* can be used as x or y coordinates to cause a specific placement */ Darkvater@5664: enum WindowDefaultPosition { Darkvater@5072: WDP_AUTO = -1, ///< Find a place automatically Darkvater@5072: WDP_CENTER = -2, ///< Center the window (left/right or top/bottom) Darkvater@5072: WDP_ALIGN_TBR = -3, ///< Align the right side of the window with the right side of the main toolbar Darkvater@5072: WDP_ALIGN_TBL = -4, ///< Align the left side of the window with the left side of the main toolbar truelight@0: }; truelight@0: rubidium@6574: struct Textbuf { belugas@6443: char *buf; ///< buffer in which text is saved belugas@6443: uint16 maxlength, maxwidth; ///< the maximum size of the buffer. Maxwidth specifies screensize in pixels, maxlength is in bytes belugas@6443: uint16 length, width; ///< the current size of the string. Width specifies screensize in pixels, length is in bytes belugas@6443: bool caret; ///< is the caret ("_") visible or not belugas@6443: uint16 caretpos; ///< the current position of the caret in the buffer, in bytes belugas@6443: uint16 caretxoffs; ///< the current position of the caret in pixels rubidium@6574: }; Darkvater@1390: truelight@0: #define WP(ptr,str) (*(str*)(ptr)->custom) Darkvater@2906: /* You cannot 100% reliably calculate the biggest custom struct as Darkvater@2906: * the number of pointers in it and alignment will have a huge impact. truelight@4299: * 96 is the largest window-size for 64-bit machines currently */ truelight@4299: #define WINDOW_CUSTOM_SIZE 96 truelight@0: rubidium@6574: struct Scrollbar { dominik@62: uint16 count, cap, pos; rubidium@6574: }; truelight@0: rubidium@6574: struct ResizeInfo { belugas@6443: uint width; ///< Minimum width and height truelight@867: uint height; belugas@6443: uint step_width; ///< In how big steps the width and height go truelight@867: uint step_height; rubidium@6574: }; truelight@867: rubidium@6574: struct WindowMessage { rubidium@6574: int msg; rubidium@6574: int wparam; rubidium@6574: int lparam; rubidium@6574: }; darkvater@1648: truelight@0: struct Window { truelight@0: uint16 flags4; truelight@0: WindowClass window_class; truelight@0: WindowNumber window_number; truelight@0: truelight@867: int left, top; truelight@867: int width, height; truelight@0: bjarni@842: Scrollbar hscroll, vscroll, vscroll2; truelight@867: ResizeInfo resize; truelight@0: truelight@0: byte caption_color; truelight@0: truelight@0: WindowProc *wndproc; truelight@0: ViewPort *viewport; truelight@867: const Widget *original_widget; tron@4077: Widget *widget; rubidium@5232: uint widget_count; truelight@0: uint32 desc_flags; truelight@0: truelight@2622: WindowMessage message; Darkvater@5666: Window *parent; truelight@158: byte custom[WINDOW_CUSTOM_SIZE]; truelight@0: }; truelight@0: rubidium@6574: struct querystr_d { truelight@4299: StringID caption; truelight@4299: Textbuf text; truelight@4299: const char *orig; truelight@4299: CharSetFilter afilter; Darkvater@5682: bool handled; rubidium@6574: }; truelight@4299: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(querystr_d)); truelight@4299: rubidium@7027: struct chatquerystr_d : public querystr_d { rubidium@7027: int dest; rubidium@7027: }; rubidium@7027: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(chatquerystr_d)); rubidium@7027: rubidium@6574: struct menu_d { belugas@6443: byte item_count; ///< follow_vehicle belugas@6443: byte sel_index; ///< scrollpos_x belugas@6443: byte main_button; ///< scrollpos_y truelight@0: byte action_id; belugas@6443: StringID string_id; ///< unk30 belugas@6443: uint16 checked_items; ///< unk32 celestar@2216: byte disabled_items; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(menu_d)); truelight@0: rubidium@6574: struct def_d { truelight@0: int16 data_1, data_2, data_3; truelight@0: int16 data_4, data_5; tron@2596: bool close; truelight@0: byte byte_1; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(def_d)); truelight@0: rubidium@6574: struct void_d { truelight@0: void *data; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(void_d)); truelight@0: rubidium@6574: struct tree_d { tron@2596: uint16 base; tron@2596: uint16 count; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tree_d)); truelight@0: rubidium@6574: struct tooltips_d { truelight@0: StringID string_id; Darkvater@4834: byte paramcount; rubidium@7502: uint64 params[5]; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tooltips_d)); truelight@0: rubidium@6574: struct buildvehicle_d { rubidium@7134: VehicleType vehicle_type; KUDr@5187: union { rubidium@5838: RailTypeByte railtype; tron@6350: AirportFTAClass::Flags flags; rubidium@7162: RoadTypes roadtypes; KUDr@5187: } filter; belugas@6443: byte sel_index; ///< deprecated value, used for 'unified' ship and road KUDr@5187: bool descending_sort_order; bjarni@4770: byte sort_criteria; bjarni@6032: bool regenerate_list; tron@2498: EngineID sel_engine; tron@2498: EngineID rename_engine; KUDr@5187: EngineList eng_list; rubidium@6574: }; bjarni@4790: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(buildvehicle_d)); truelight@0: rubidium@6574: struct replaceveh_d { bjarni@842: byte sel_index[2]; peter1138@2746: EngineID sel_engine[2]; bjarni@842: uint16 count[2]; belugas@6443: bool wagon_btnstate; ///< true means engine is selected bjarni@6195: EngineList list[2]; bjarni@6195: bool update_left; bjarni@6195: bool update_right; bjarni@6195: bool init_lists; rubidium@7139: GroupID sel_group; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(replaceveh_d)); bjarni@842: rubidium@6574: struct depot_d { truelight@0: VehicleID sel; rubidium@7134: VehicleType type; bjarni@4739: bool generate_list; bjarni@4635: uint16 engine_list_length; bjarni@4635: uint16 wagon_list_length; bjarni@4635: uint16 engine_count; bjarni@4635: uint16 wagon_count; bjarni@4635: Vehicle **vehicle_list; bjarni@4635: Vehicle **wagon_list; rubidium@6574: }; bjarni@4638: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(depot_d)); truelight@0: rubidium@6574: struct order_d { truelight@0: int sel; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(order_d)); truelight@0: rubidium@8026: struct vehicledetails_d { truelight@0: byte tab; rubidium@6574: }; rubidium@8026: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehicledetails_d)); truelight@0: rubidium@6574: struct smallmap_d { tron@849: int32 scroll_x; tron@849: int32 scroll_y; tron@849: int32 subscroll; rubidium@6574: }; truelight@4318: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(smallmap_d)); truelight@0: rubidium@8230: /* player face selection window */ rubidium@6574: struct facesel_d { rubidium@8230: PlayerFace face; // player face bits rubidium@8230: bool advanced; // advance player face selection window rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(facesel_d)); truelight@0: rubidium@6574: struct refit_d { truelight@0: int sel; peter1138@4695: struct RefitOption *cargo; peter1138@4694: struct RefitList *list; peter1138@4694: uint length; bjarni@4712: VehicleOrderID order; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(refit_d)); truelight@0: rubidium@6574: struct vp_d { tron@2116: VehicleID follow_vehicle; tron@849: int32 scrollpos_x; tron@849: int32 scrollpos_y; peter1138@7226: int32 dest_scrollpos_x; peter1138@7226: int32 dest_scrollpos_y; rubidium@6574: }; Darkvater@5123: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vp_d)); miham@1004: rubidium@6574: struct news_d { truelight@0: uint16 follow_vehicle; tron@849: int32 scrollpos_x; tron@849: int32 scrollpos_y; peter1138@7226: int32 dest_scrollpos_x; peter1138@7226: int32 dest_scrollpos_y; truelight@0: NewsItem *ni; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(news_d)); truelight@0: rubidium@6574: struct highscore_d { darkvater@998: uint32 background_img; darkvater@998: int8 rank; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(highscore_d)); darkvater@998: rubidium@6574: struct scroller_d { darkvater@998: int height; darkvater@998: uint16 counter; rubidium@6574: }; miham@1004: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(scroller_d)); darkvater@859: rubidium@6574: enum SortListFlags { belugas@6505: VL_NONE = 0x00, ///< no sort belugas@6443: VL_DESC = 0x01, ///< sort descending or ascending belugas@6443: VL_RESORT = 0x02, ///< instruct the code to resort the list in the next loop belugas@6443: VL_REBUILD = 0x04, ///< create sort-listing to use for qsort and friends rubidium@5838: VL_END = 0x08 rubidium@6574: }; tron@588: rubidium@5838: DECLARE_ENUM_AS_BIT_SET(SortListFlags); rubidium@5838: rubidium@6574: struct Listing { belugas@6443: bool order; ///< Ascending/descending belugas@6443: byte criteria; ///< Sorting criteria rubidium@6574: }; tron@588: rubidium@6574: struct list_d { belugas@6443: uint16 list_length; ///< length of the list being sorted belugas@6443: byte sort_type; ///< what criteria to sort on belugas@6443: SortListFlags flags; ///< used to control sorting/resorting/etc. belugas@6443: uint16 resort_timer; ///< resort list after a given amount of ticks if set rubidium@6574: }; Darkvater@2888: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(list_d)); Darkvater@2888: rubidium@6574: struct message_d { darkvater@1648: int msg; darkvater@1648: int wparam; darkvater@1648: int lparam; rubidium@6574: }; darkvater@1648: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(message_d)); darkvater@1648: rubidium@6574: struct dropdown_d { peter1138@2683: uint32 disabled_state; peter1138@2683: uint32 hidden_state; peter1138@2636: WindowClass parent_wnd_class; peter1138@2636: WindowNumber parent_wnd_num; peter1138@2636: byte parent_button; peter1138@2636: byte num_items; peter1138@2636: byte selected_index; peter1138@2636: const StringID *items; peter1138@2636: byte click_delay; peter1138@2636: bool drag_mode; rubidium@6574: }; peter1138@2636: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(dropdown_d)); peter1138@2636: rubidium@7139: struct vehiclelist_d { rubidium@7139: const Vehicle** sort_list; // List of vehicles (sorted) rubidium@7139: Listing *_sorting; // pointer to the appropiate subcategory of _sorting rubidium@7139: uint16 length_of_sort_list; // Keeps track of how many vehicle pointers sort list got space for rubidium@7139: VehicleType vehicle_type; // The vehicle type that is sorted rubidium@7139: list_d l; // General list struct rubidium@7139: }; rubidium@7139: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehiclelist_d)); rubidium@7139: rubidium@7139: struct grouplist_d { rubidium@7139: const Group **sort_list; rubidium@7139: list_d l; // General list struct rubidium@7139: }; rubidium@7139: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(grouplist_d)); rubidium@7139: rubidium@7139: struct groupveh_d : vehiclelist_d { rubidium@7139: GroupID group_sel; rubidium@7139: VehicleID vehicle_sel; rubidium@7139: rubidium@7139: grouplist_d gl; rubidium@7139: }; rubidium@7139: assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(groupveh_d)); truelight@0: truelight@0: /****************** THESE ARE NOT WIDGET TYPES!!!!! *******************/ truelight@0: enum WindowWidgetBehaviours { rubidium@4344: WWB_PUSHBUTTON = 1 << 5, Darkvater@4938: Darkvater@4938: WWB_MASK = 0xE0, truelight@0: }; truelight@0: truelight@0: truelight@0: enum WindowWidgetTypes { Darkvater@4939: WWT_EMPTY, truelight@158: belugas@6443: WWT_PANEL, ///< simple depressed panel belugas@6443: WWT_INSET, ///< pressed (inset) panel, most commonly used as combo box _text_ area belugas@6443: WWT_IMGBTN, ///< button with image belugas@6443: WWT_IMGBTN_2, ///< button with diff image when clicked Darkvater@4938: belugas@6443: WWT_TEXTBTN, ///< button with text belugas@6443: WWT_TEXTBTN_2, ///< button with diff text when clicked belugas@6443: WWT_LABEL, ///< centered label belugas@6604: WWT_TEXT, ///< pure simple text Darkvater@4939: WWT_MATRIX, Darkvater@4939: WWT_SCROLLBAR, belugas@6443: WWT_FRAME, ///< frame Darkvater@4939: WWT_CAPTION, truelight@0: Darkvater@4939: WWT_HSCROLLBAR, Darkvater@4939: WWT_STICKYBOX, belugas@6443: WWT_SCROLL2BAR, ///< 2nd vertical scrollbar Darkvater@4939: WWT_RESIZEBOX, Darkvater@4939: WWT_CLOSEBOX, belugas@6443: WWT_LAST, ///< Last Item. use WIDGETS_END to fill up padding!! Darkvater@4939: Darkvater@4939: WWT_MASK = 0x1F, truelight@0: Darkvater@4938: WWT_PUSHBTN = WWT_PANEL | WWB_PUSHBUTTON, rubidium@4434: WWT_PUSHTXTBTN = WWT_TEXTBTN | WWB_PUSHBUTTON, rubidium@4434: WWT_PUSHIMGBTN = WWT_IMGBTN | WWB_PUSHBUTTON, truelight@0: }; truelight@0: truelight@867: #define WIDGETS_END WWT_LAST, RESIZE_NONE, 0, 0, 0, 0, 0, 0, STR_NULL darkvater@176: truelight@0: enum WindowFlags { rubidium@4344: WF_TIMEOUT_SHL = 0, rubidium@4344: WF_TIMEOUT_MASK = 7, rubidium@4344: WF_DRAGGING = 1 << 3, rubidium@4344: WF_SCROLL_UP = 1 << 4, rubidium@4344: WF_SCROLL_DOWN = 1 << 5, rubidium@4344: WF_SCROLL_MIDDLE = 1 << 6, rubidium@4344: WF_HSCROLL = 1 << 7, rubidium@4344: WF_SIZING = 1 << 8, rubidium@4344: WF_STICKY = 1 << 9, truelight@867: truelight@0: WF_DISABLE_VP_SCROLL = 1 << 10, truelight@0: rubidium@4344: WF_WHITE_BORDER_ONE = 1 << 11, Darkvater@5667: WF_WHITE_BORDER_MASK = 1 << 12 | WF_WHITE_BORDER_ONE, rubidium@4344: WF_SCROLL2 = 1 << 13, truelight@0: }; truelight@0: belugas@6443: /* window.cpp */ truelight@0: void CallWindowEventNP(Window *w, int event); rubidium@6573: void CallWindowTickEvent(); rubidium@8041: rubidium@8041: /** rubidium@8041: * Marks the window as dirty for repaint. rubidium@8041: * rubidium@8041: * @ingroup dirty rubidium@8041: */ belugas@4171: void SetWindowDirty(const Window *w); rubidium@5838: void SendWindowMessage(WindowClass wnd_class, WindowNumber wnd_num, int msg, int wparam, int lparam); rubidium@5838: void SendWindowMessageClass(WindowClass wnd_class, int msg, int wparam, int lparam); truelight@0: truelight@0: Window *FindWindowById(WindowClass cls, WindowNumber number); truelight@0: void DeleteWindow(Window *w); bjarni@5077: void DeletePlayerWindows(PlayerID pi); bjarni@5077: void ChangeWindowOwner(PlayerID old_player, PlayerID new_player); truelight@0: Window *BringWindowToFrontById(WindowClass cls, WindowNumber number); truelight@0: Window *FindWindowFromPt(int x, int y); truelight@0: belugas@4171: bool IsWindowOfPrototype(const Window *w, const Widget *widget); truelight@867: void AssignWidgetToWindow(Window *w, const Widget *widget); truelight@0: Window *AllocateWindow( truelight@0: int x, truelight@0: int y, truelight@0: int width, truelight@0: int height, truelight@158: WindowProc *proc, truelight@0: WindowClass cls, rubidium@7863: const Widget *widget, rubidium@7863: void *data = NULL); truelight@0: rubidium@7863: Window *AllocateWindowDesc(const WindowDesc *desc, void *data = NULL); rubidium@7863: Window *AllocateWindowDescFront(const WindowDesc *desc, int window_number, void *data = NULL); truelight@0: Darkvater@5120: void DrawWindowViewport(const Window *w); Darkvater@5268: void ResizeWindow(Window *w, int x, int y); truelight@0: belugas@4692: /** belugas@4692: * Sets the enabled/disabled status of a widget. belugas@4692: * By default, widgets are enabled. belugas@4692: * On certain conditions, they have to be disabled. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: * @param disab_stat : status to use ie: disabled = true, enabled = false belugas@4692: */ belugas@4692: static inline void SetWindowWidgetDisabledState(Window *w, byte widget_index, bool disab_stat) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); belugas@4749: SB(w->widget[widget_index].display_flags, WIDG_DISABLED, 1, !!disab_stat); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Sets a widget to disabled. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void DisableWindowWidget(Window *w, byte widget_index) belugas@4692: { belugas@4692: SetWindowWidgetDisabledState(w, widget_index, true); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Sets a widget to Enabled. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void EnableWindowWidget(Window *w, byte widget_index) belugas@4692: { belugas@4692: SetWindowWidgetDisabledState(w, widget_index, false); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Gets the enabled/disabled status of a widget. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: * @return status of the widget ie: disabled = true, enabled = false belugas@4692: */ rubidium@5233: static inline bool IsWindowWidgetDisabled(const Window *w, byte widget_index) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); rubidium@5236: return HASBIT(w->widget[widget_index].display_flags, WIDG_DISABLED); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Sets the hidden/shown status of a widget. belugas@4692: * By default, widgets are visible. belugas@4692: * On certain conditions, they have to be hidden. belugas@4692: * @param w Window on which the widget is located belugas@4692: * @param widget_index index of this widget in the window belugas@4692: * @param hidden_stat status to use ie. hidden = true, visible = false belugas@4692: */ belugas@4692: static inline void SetWindowWidgetHiddenState(Window *w, byte widget_index, bool hidden_stat) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); belugas@4749: SB(w->widget[widget_index].display_flags, WIDG_HIDDEN, 1, !!hidden_stat); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Sets a widget hidden. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void HideWindowWidget(Window *w, byte widget_index) belugas@4692: { belugas@4692: SetWindowWidgetHiddenState(w, widget_index, true); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Sets a widget visible. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void ShowWindowWidget(Window *w, byte widget_index) belugas@4692: { belugas@4692: SetWindowWidgetHiddenState(w, widget_index, false); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Gets the visibility of a widget. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: * @return status of the widget ie: hidden = true, visible = false belugas@4692: */ rubidium@5233: static inline bool IsWindowWidgetHidden(const Window *w, byte widget_index) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); rubidium@5236: return HASBIT(w->widget[widget_index].display_flags, WIDG_HIDDEN); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Sets the lowered/raised status of a widget. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@6928: * @param lowered_stat : status to use ie: lowered = true, raised = false belugas@4692: */ belugas@4727: static inline void SetWindowWidgetLoweredState(Window *w, byte widget_index, bool lowered_stat) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); belugas@4749: SB(w->widget[widget_index].display_flags, WIDG_LOWERED, 1, !!lowered_stat); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Invert the lowered/raised status of a widget. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void ToggleWidgetLoweredState(Window *w, byte widget_index) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); belugas@4749: TOGGLEBIT(w->widget[widget_index].display_flags, WIDG_LOWERED); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Marks a widget as lowered. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void LowerWindowWidget(Window *w, byte widget_index) belugas@4692: { glx@4730: SetWindowWidgetLoweredState(w, widget_index, true); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Marks a widget as raised. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: */ belugas@4692: static inline void RaiseWindowWidget(Window *w, byte widget_index) belugas@4692: { glx@4730: SetWindowWidgetLoweredState(w, widget_index, false); belugas@4692: } belugas@4692: belugas@4692: /** belugas@4692: * Gets the lowered state of a widget. belugas@4692: * @param w : Window on which the widget is located belugas@4692: * @param widget_index : index of this widget in the window belugas@4692: * @return status of the widget ie: lowered = true, raised= false belugas@4692: */ rubidium@5233: static inline bool IsWindowWidgetLowered(const Window *w, byte widget_index) belugas@4692: { rubidium@5232: assert(widget_index < w->widget_count); belugas@4749: return HASBIT(w->widget[widget_index].display_flags, WIDG_LOWERED); belugas@4692: } belugas@4692: rubidium@6573: void InitWindowSystem(); rubidium@6573: void UnInitWindowSystem(); rubidium@6573: void ResetWindowSystem(); Darkvater@2436: int GetMenuItemIndex(const Window *w, int x, int y); rubidium@6573: void InputLoop(); belugas@4171: void InvalidateWidget(const Window *w, byte widget_index); bjarni@4766: void InvalidateThisWindowData(Window *w); bjarni@4739: void InvalidateWindowData(WindowClass cls, WindowNumber number); belugas@4719: void RaiseWindowButtons(Window *w); truelight@0: void RelocateAllWindows(int neww, int newh); tron@380: int PositionMainToolbar(Window *w); glx@4755: void CDECL SetWindowWidgetsDisabledState(Window *w, bool disab_stat, int widgets, ...); glx@4755: void CDECL SetWindowWidgetsHiddenState(Window *w, bool hidden_stat, int widgets, ...); glx@4755: void CDECL SetWindowWidgetsLoweredState(Window *w, bool lowered_stat, int widgets, ...); truelight@0: belugas@6443: /* misc_gui.cpp */ rubidium@7502: void GuiShowTooltipsWithArgs(StringID str, uint paramcount, const uint64 params[]); Darkvater@4834: static inline void GuiShowTooltips(StringID str) Darkvater@4834: { Darkvater@4834: GuiShowTooltipsWithArgs(str, 0, NULL); Darkvater@4834: } belugas@4719: belugas@6443: /* widget.cpp */ Darkvater@2436: int GetWidgetFromPos(const Window *w, int x, int y); Darkvater@2436: void DrawWindowWidgets(const Window *w); peter1138@2448: void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask); truelight@0: truelight@0: void HandleButtonClick(Window *w, byte widget); truelight@0: rubidium@6573: Window *GetCallbackWnd(); rubidium@6573: void DeleteNonVitalWindows(); rubidium@6573: void DeleteAllNonVitalWindows(); rubidium@6573: void HideVitalWindows(); rubidium@6573: void ShowVitalWindows(); Darkvater@5124: Window **FindWindowZPosition(const Window *w); truelight@0: belugas@6443: /* window.cpp */ Darkvater@5124: extern Window *_z_windows[]; Darkvater@5124: extern Window **_last_z_window; Darkvater@5124: #define FOR_ALL_WINDOWS(wz) for (wz = _z_windows; wz != _last_z_window; wz++) truelight@0: truelight@0: VARDEF Point _cursorpos_drag_start; truelight@0: truelight@0: VARDEF int _scrollbar_start_pos; truelight@0: VARDEF int _scrollbar_size; truelight@0: VARDEF byte _scroller_click_timeout; truelight@0: truelight@0: VARDEF bool _scrolling_scrollbar; truelight@0: VARDEF bool _scrolling_viewport; truelight@0: VARDEF bool _popup_menu_active; truelight@0: truelight@0: VARDEF byte _special_mouse_mode; truelight@0: enum SpecialMouseMode { rubidium@4344: WSM_NONE = 0, truelight@0: WSM_DRAGDROP = 1, rubidium@4344: WSM_SIZING = 2, rubidium@4344: WSM_PRESIZE = 3, truelight@0: }; truelight@0: truelight@0: void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y); truelight@0: bjarni@6073: /** Evenly distribute some widgets when resizing horizontally (often a button row) bjarni@6075: * The widgets are presumed to be in a line and numberef from left to right (without gaps) bjarni@6073: * @param w widow to modify bjarni@6073: * @param left The leftmost widget to resize bjarni@6075: * @param right The rightmost widget to resize. Since right side of it is used, remember to set it to RESIZE_RIGHT bjarni@6073: */ bjarni@6073: void ResizeButtons(Window *w, byte left, byte right); bjarni@6073: truelight@0: #endif /* WINDOW_H */