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