1 // SciTE - Scintilla based Text Editor 2 /** @file StripDefinition.h 3 ** Definition of classes build user strips from a description string. 4 **/ 5 // Copyright 2012 by Neil Hodgson <neilh@scintilla.org> 6 // The License.txt file describes the conditions under which this software may be distributed. 7 8 #ifndef STRIPDEFINITION_H 9 #define STRIPDEFINITION_H 10 11 class UserControl { 12 public: 13 enum UCControlType { ucStatic, ucEdit, ucCombo, ucButton, ucDefaultButton } controlType; 14 GUI::gui_string text; 15 int item; 16 bool fixedWidth; 17 int widthDesired; 18 int widthAllocated; 19 GUI::Window w; UserControl(UCControlType controlType_,const GUI::gui_string & text_,int item_)20 UserControl(UCControlType controlType_, const GUI::gui_string &text_, int item_) : 21 controlType(controlType_), 22 text(text_), 23 item(item_), 24 fixedWidth(true), 25 widthDesired(20), 26 widthAllocated(20) { 27 } 28 }; 29 30 struct ColumnWidth { 31 int widthDesired; 32 int widthAllocated; 33 bool isResizeable; ColumnWidthColumnWidth34 ColumnWidth() noexcept : widthDesired(0), widthAllocated(0), isResizeable(false) { 35 } 36 }; 37 38 class StripDefinition { 39 public: 40 bool hasClose; 41 unsigned int columns; 42 std::vector<std::vector<UserControl> > controls; 43 std::vector<ColumnWidth> widths; 44 StripDefinition(GUI::gui_string definition)45 explicit StripDefinition(GUI::gui_string definition) { 46 hasClose = false; 47 controls.clear(); 48 columns = 0; 49 controls.push_back(std::vector<UserControl>()); 50 const GUI::gui_char *pdef=definition.c_str(); 51 int line = 0; 52 unsigned int column = 0; 53 int item = 0; 54 while (*pdef) { 55 if (*pdef == '\n') { 56 controls.push_back(std::vector<UserControl>()); 57 column = 0; 58 line++; 59 pdef++; 60 continue; 61 } 62 if (*pdef == '!') { 63 hasClose = true; 64 pdef++; 65 continue; 66 } 67 UserControl::UCControlType controlType = UserControl::ucStatic; 68 GUI::gui_char endChar = 0; 69 switch (*pdef) { 70 case '\'': 71 controlType = UserControl::ucStatic; 72 endChar = '\''; 73 break; 74 case '[': 75 controlType = UserControl::ucEdit; 76 endChar = ']'; 77 break; 78 case '{': 79 controlType = UserControl::ucCombo; 80 endChar = '}'; 81 break; 82 case '(': 83 if (pdef[1] == '(') { 84 controlType = UserControl::ucDefaultButton; 85 pdef++; 86 } else { 87 controlType = UserControl::ucButton; 88 } 89 endChar = ')'; 90 break; 91 } 92 pdef++; 93 GUI::gui_string text; 94 while (*pdef && (*pdef != endChar)) { 95 text += *pdef; 96 pdef++; 97 } 98 if ((controlType == UserControl::ucDefaultButton) && *pdef) 99 pdef++; 100 controls.back().push_back(UserControl(controlType, text, item)); 101 column++; 102 if (columns < column) 103 columns = column; 104 if (*pdef) 105 pdef++; 106 item++; 107 } 108 } 109 CalculateColumnWidths(int widthToAllocate)110 void CalculateColumnWidths(int widthToAllocate) { 111 widths.clear(); 112 113 int widthOfNonResizeables = 4 * (columns - 1); 114 int resizeables = 0; 115 for (size_t column=0; column<columns; column++) { 116 ColumnWidth cw; 117 for (size_t line=0; line<controls.size(); line++) { 118 if (column < controls[line].size()) { 119 const UserControl *ctl = &controls[line][column]; 120 if (ctl->fixedWidth) { 121 if (cw.widthDesired < ctl->widthDesired) 122 cw.widthDesired = ctl->widthDesired; 123 } else { 124 cw.isResizeable = true; 125 } 126 } 127 } 128 widths.push_back(cw); 129 widthOfNonResizeables += cw.widthDesired; 130 if (cw.isResizeable) 131 resizeables++; 132 } 133 const int widthSpareEach = resizeables ? 134 (widthToAllocate - widthOfNonResizeables) / resizeables : 0; 135 for (std::vector<ColumnWidth>::iterator cw=widths.begin(); cw != widths.end(); ++cw) { 136 if (cw->isResizeable) { 137 cw->widthAllocated = widthSpareEach + cw->widthDesired; 138 } else { 139 cw->widthAllocated = cw->widthDesired; 140 } 141 } 142 } 143 FindControl(int control)144 UserControl *FindControl(int control) { 145 int controlID=0; 146 for (std::vector<std::vector<UserControl> >::iterator line=controls.begin(); line != controls.end(); ++line) { 147 for (std::vector<UserControl>::iterator ctl=line->begin(); ctl != line->end(); ++ctl) { 148 if (controlID == control) { 149 return &(*ctl); 150 } 151 controlID++; 152 } 153 } 154 return nullptr; 155 } 156 }; 157 158 enum StripCommand { scUnknown, scClicked, scChange, scFocusIn, scFocusOut }; 159 160 #endif 161