GacUI Demo:文本框基本应用
GacUI添加了一个新的Demo。这个Demo用了几个按钮(之所以不用菜单是因为不想让Demo一下子包含太多新东西)来实现剪贴板操作、只读控制和行跳转等功能。在剪贴板里面的内容是文字的时候,Paste按钮会被Enable。这个过程是自动的,也就是说,你在画图里面复制了一个图片,这个按钮也会变灰。Cut和Copy按钮仅在文本框有文字被选中的时候可用,因此相应了文本框的SelectionChanged来处理这件事情。如果文本框的内容太多的话,{VS, Explorer} X {Debug, Release}这四种运行方法里面,只有在Debug模式下挂了VS这种情况会感觉有点卡,其他的打开方法都是很流畅的。先来看图:
代码还是比较简单的。先用一个Table分成三行,前两行让行高缩短到最短,最后一行则利用了剩余空间的100%撑开。前两行里面的按钮用Stack来对它们进行排版。单行文本框没有最小高度,所以依靠Stack和Table,它的高度会保持跟按钮一致。代码如下:
GacUI将提供两个文本框的Demo,这是第一个。GacUI的文本框从一开始就具备了让每一个字符的颜色可以不同的功能,下一个Demo将展示如何利用使用正则表达式构建的词法分析器(见 这里和 这里),让文本框在编辑的时候,跟所有的代码编辑器一样,可以根据情况把不同的字符串染成不同的颜色。
代码还是比较简单的。先用一个Table分成三行,前两行让行高缩短到最短,最后一行则利用了剩余空间的100%撑开。前两行里面的按钮用Stack来对它们进行排版。单行文本框没有最小高度,所以依靠Stack和Table,它的高度会保持跟按钮一致。代码如下:
1
#include
"
..\..\Public\Source\GacUIIncludes.h
"
2 #include < Windows.h >
3
4 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
5 {
6 return SetupWindowsDirect2DRenderer();
7 }
8
9 class TextBoxEditorWindow : public GuiWindow
10 {
11 private :
12 GuiButton * buttonCut;
13 GuiButton * buttonCopy;
14 GuiButton * buttonPaste;
15 GuiButton * buttonSelectAll;
16 GuiSelectableButton * checkReadonly;
17 GuiSinglelineTextBox * textGoto;
18 GuiButton * buttonGoto;
19 GuiMultilineTextBox * textDocument;
20
21 void UpdateEditButtonState()
22 {
23 buttonCut -> SetEnabled(textDocument -> CanCut());
24 buttonCopy -> SetEnabled(textDocument -> CanCopy());
25 buttonPaste -> SetEnabled(textDocument -> CanPaste());
26 }
27
28 // ensure that the buttonGoto is enabled only when textGoto's content is a positive number
29 void UpdateGotoButtonState()
30 {
31 buttonGoto -> SetEnabled(utow(wtou(textGoto -> GetText())) == textGoto -> GetText() && wtou(textGoto -> GetText()) != 0 );
32 }
33
34 // cut text box selection
35 void buttonCut_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
36 {
37 textDocument -> Cut();
38 textDocument -> SetFocus();
39 }
40
41 // copy text box selection
42 void buttonCopy_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
43 {
44 textDocument -> Copy();
45 textDocument -> SetFocus();
46 }
47
48 // paste text from clipboard
49 void buttonPaste_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
50 {
51 textDocument -> Paste();
52 textDocument -> SetFocus();
53 }
54
55 // select all text
56 void buttonSelectAll_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
57 {
58 textDocument -> SelectAll();
59 textDocument -> SetFocus();
60 }
61
62 // go to the specified line
63 void buttonGoto_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
64 {
65 int line = wtoi(textGoto -> GetText()) - 1 ;
66 textDocument -> Select(TextPos(line, 0 ), TextPos(line, 0 ));
67 textDocument -> SetFocus();
68 }
69
70 // make the textbox readonly or not readonly
71 void checkReadonly_OnSelectedChanged(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
72 {
73 textDocument -> SetReadonly(checkReadonly -> GetSelected());
74 UpdateEditButtonState();
75 }
76
77 // when textGoto changed, disable buttonGoto if the text in the textGoto is failed to pass the validation
78 void textGoto_TextChanged(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
79 {
80 UpdateGotoButtonState();
81 }
82
83 // update the edit buttons when selection changed
84 void textDocument_SelectionChanged(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
85 {
86 UpdateEditButtonState();
87 }
88
89 // update the edit buttons when clipboard changed changed
90 void window_OnClipboardUpdated(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
91 {
92 UpdateEditButtonState();
93 }
94 public :
95 TextBoxEditorWindow()
96 :GuiWindow(GetCurrentTheme() -> CreateWindowStyle())
97 {
98 this -> SetText(L " Controls.TextBox.Editor " );
99 this -> GetContainerComposition() -> SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
100 this -> ClipboardUpdated.AttachMethod( this , & TextBoxEditorWindow::window_OnClipboardUpdated);
101
102 GuiTableComposition * table = new GuiTableComposition;
103 table -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
104 table -> SetCellPadding( 2 );
105 table -> SetRowsAndColumns( 3 , 1 );
106 table -> SetRowOption( 0 , GuiCellOption::MinSizeOption());
107 table -> SetRowOption( 1 , GuiCellOption::MinSizeOption());
108 table -> SetRowOption( 2 , GuiCellOption::PercentageOption( 1.0 ));
109 table -> SetColumnOption( 0 , GuiCellOption::PercentageOption( 1.0 ));
110 this -> GetContainerComposition() -> AddChild(table);
111
112 {
113 GuiCellComposition * cell = new GuiCellComposition;
114 table -> AddChild(cell);
115 cell -> SetSite( 0 , 0 , 1 , 1 );
116
117 GuiStackComposition * stack = new GuiStackComposition;
118 stack -> SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
119 stack -> SetPadding( 2 );
120 stack -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
121 cell -> AddChild(stack);
122
123 {
124 GuiStackItemComposition * item = new GuiStackItemComposition;
125 stack -> AddChild(item);
126
127 buttonCut = g::NewButton();
128 buttonCut -> SetText(L " Cut " );
129 buttonCut -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
130 buttonCut -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonCut_OnClicked);
131 item -> AddChild(buttonCut -> GetBoundsComposition());
132 }
133 {
134 GuiStackItemComposition * item = new GuiStackItemComposition;
135 stack -> AddChild(item);
136
137 buttonCopy = g::NewButton();
138 buttonCopy -> SetText(L " Copy " );
139 buttonCopy -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
140 buttonCopy -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonCopy_OnClicked);
141 item -> AddChild(buttonCopy -> GetBoundsComposition());
142 }
143 {
144 GuiStackItemComposition * item = new GuiStackItemComposition;
145 stack -> AddChild(item);
146
147 buttonPaste = g::NewButton();
148 buttonPaste -> SetText(L " Paste " );
149 buttonPaste -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
150 buttonPaste -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonPaste_OnClicked);
151 item -> AddChild(buttonPaste -> GetBoundsComposition());
152 }
153 {
154 GuiStackItemComposition * item = new GuiStackItemComposition;
155 stack -> AddChild(item);
156
157 buttonSelectAll = g::NewButton();
158 buttonSelectAll -> SetText(L " Select All " );
159 buttonSelectAll -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
160 buttonSelectAll -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonSelectAll_OnClicked);
161 item -> AddChild(buttonSelectAll -> GetBoundsComposition());
162 }
163 {
164 GuiStackItemComposition * item = new GuiStackItemComposition;
165 stack -> AddChild(item);
166
167 checkReadonly = g::NewCheckBox();
168 checkReadonly -> SetText(L " Readonly " );
169 checkReadonly -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
170 checkReadonly -> SelectedChanged.AttachMethod( this , & TextBoxEditorWindow::checkReadonly_OnSelectedChanged);
171 item -> AddChild(checkReadonly -> GetBoundsComposition());
172 }
173 }
174 {
175 GuiCellComposition * cell = new GuiCellComposition;
176 table -> AddChild(cell);
177 cell -> SetSite( 1 , 0 , 1 , 1 );
178
179 GuiStackComposition * stack = new GuiStackComposition;
180 stack -> SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
181 stack -> SetPadding( 2 );
182 stack -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
183 cell -> AddChild(stack);
184
185 {
186 GuiStackItemComposition * item = new GuiStackItemComposition;
187 stack -> AddChild(item);
188
189 textGoto = g::NewTextBox();
190 textGoto -> GetBoundsComposition() -> SetBounds(Rect(Point( 0 , 0 ), Size( 180 , 0 )));
191 textGoto -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
192 textGoto -> TextChanged.AttachMethod( this , & TextBoxEditorWindow::textGoto_TextChanged);
193 item -> AddChild(textGoto -> GetBoundsComposition());
194 }
195 {
196 GuiStackItemComposition * item = new GuiStackItemComposition;
197 stack -> AddChild(item);
198
199 buttonGoto = g::NewButton();
200 buttonGoto -> SetText(L " Go to this line " );
201 buttonGoto -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
202 buttonGoto -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonGoto_OnClicked);
203 item -> AddChild(buttonGoto -> GetBoundsComposition());
204 }
205 }
206 {
207 GuiCellComposition * cell = new GuiCellComposition;
208 table -> AddChild(cell);
209 cell -> SetSite( 2 , 0 , 1 , 1 );
210
211 textDocument = g::NewMultilineTextBox();
212 textDocument -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
213 textDocument -> SelectionChanged.AttachMethod( this , & TextBoxEditorWindow::textDocument_SelectionChanged);
214 cell -> AddChild(textDocument -> GetBoundsComposition());
215 }
216
217 // make some buttons enabled or disabled appropiately
218 UpdateEditButtonState();
219 UpdateGotoButtonState();
220 // set the preferred minimum client size
221 this -> GetBoundsComposition() -> SetPreferredMinSize(Size( 640 , 480 ));
222 // call this to calculate the size immediately if any indirect content in the table changes
223 // so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
224 this -> ForceCalculateSizeImmediately();
225 // move to the screen center
226 this -> MoveToScreenCenter();
227 }
228
229 ~ TextBoxEditorWindow()
230 {
231 }
232 };
233
234 void GuiMain()
235 {
236 GuiWindow * window = new TextBoxEditorWindow();
237 GetApplication() -> Run(window);
238 delete window;
239 }
2 #include < Windows.h >
3
4 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
5 {
6 return SetupWindowsDirect2DRenderer();
7 }
8
9 class TextBoxEditorWindow : public GuiWindow
10 {
11 private :
12 GuiButton * buttonCut;
13 GuiButton * buttonCopy;
14 GuiButton * buttonPaste;
15 GuiButton * buttonSelectAll;
16 GuiSelectableButton * checkReadonly;
17 GuiSinglelineTextBox * textGoto;
18 GuiButton * buttonGoto;
19 GuiMultilineTextBox * textDocument;
20
21 void UpdateEditButtonState()
22 {
23 buttonCut -> SetEnabled(textDocument -> CanCut());
24 buttonCopy -> SetEnabled(textDocument -> CanCopy());
25 buttonPaste -> SetEnabled(textDocument -> CanPaste());
26 }
27
28 // ensure that the buttonGoto is enabled only when textGoto's content is a positive number
29 void UpdateGotoButtonState()
30 {
31 buttonGoto -> SetEnabled(utow(wtou(textGoto -> GetText())) == textGoto -> GetText() && wtou(textGoto -> GetText()) != 0 );
32 }
33
34 // cut text box selection
35 void buttonCut_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
36 {
37 textDocument -> Cut();
38 textDocument -> SetFocus();
39 }
40
41 // copy text box selection
42 void buttonCopy_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
43 {
44 textDocument -> Copy();
45 textDocument -> SetFocus();
46 }
47
48 // paste text from clipboard
49 void buttonPaste_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
50 {
51 textDocument -> Paste();
52 textDocument -> SetFocus();
53 }
54
55 // select all text
56 void buttonSelectAll_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
57 {
58 textDocument -> SelectAll();
59 textDocument -> SetFocus();
60 }
61
62 // go to the specified line
63 void buttonGoto_OnClicked(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
64 {
65 int line = wtoi(textGoto -> GetText()) - 1 ;
66 textDocument -> Select(TextPos(line, 0 ), TextPos(line, 0 ));
67 textDocument -> SetFocus();
68 }
69
70 // make the textbox readonly or not readonly
71 void checkReadonly_OnSelectedChanged(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
72 {
73 textDocument -> SetReadonly(checkReadonly -> GetSelected());
74 UpdateEditButtonState();
75 }
76
77 // when textGoto changed, disable buttonGoto if the text in the textGoto is failed to pass the validation
78 void textGoto_TextChanged(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
79 {
80 UpdateGotoButtonState();
81 }
82
83 // update the edit buttons when selection changed
84 void textDocument_SelectionChanged(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
85 {
86 UpdateEditButtonState();
87 }
88
89 // update the edit buttons when clipboard changed changed
90 void window_OnClipboardUpdated(GuiGraphicsComposition * sender, GuiEventArgs & arguments)
91 {
92 UpdateEditButtonState();
93 }
94 public :
95 TextBoxEditorWindow()
96 :GuiWindow(GetCurrentTheme() -> CreateWindowStyle())
97 {
98 this -> SetText(L " Controls.TextBox.Editor " );
99 this -> GetContainerComposition() -> SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
100 this -> ClipboardUpdated.AttachMethod( this , & TextBoxEditorWindow::window_OnClipboardUpdated);
101
102 GuiTableComposition * table = new GuiTableComposition;
103 table -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
104 table -> SetCellPadding( 2 );
105 table -> SetRowsAndColumns( 3 , 1 );
106 table -> SetRowOption( 0 , GuiCellOption::MinSizeOption());
107 table -> SetRowOption( 1 , GuiCellOption::MinSizeOption());
108 table -> SetRowOption( 2 , GuiCellOption::PercentageOption( 1.0 ));
109 table -> SetColumnOption( 0 , GuiCellOption::PercentageOption( 1.0 ));
110 this -> GetContainerComposition() -> AddChild(table);
111
112 {
113 GuiCellComposition * cell = new GuiCellComposition;
114 table -> AddChild(cell);
115 cell -> SetSite( 0 , 0 , 1 , 1 );
116
117 GuiStackComposition * stack = new GuiStackComposition;
118 stack -> SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
119 stack -> SetPadding( 2 );
120 stack -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
121 cell -> AddChild(stack);
122
123 {
124 GuiStackItemComposition * item = new GuiStackItemComposition;
125 stack -> AddChild(item);
126
127 buttonCut = g::NewButton();
128 buttonCut -> SetText(L " Cut " );
129 buttonCut -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
130 buttonCut -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonCut_OnClicked);
131 item -> AddChild(buttonCut -> GetBoundsComposition());
132 }
133 {
134 GuiStackItemComposition * item = new GuiStackItemComposition;
135 stack -> AddChild(item);
136
137 buttonCopy = g::NewButton();
138 buttonCopy -> SetText(L " Copy " );
139 buttonCopy -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
140 buttonCopy -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonCopy_OnClicked);
141 item -> AddChild(buttonCopy -> GetBoundsComposition());
142 }
143 {
144 GuiStackItemComposition * item = new GuiStackItemComposition;
145 stack -> AddChild(item);
146
147 buttonPaste = g::NewButton();
148 buttonPaste -> SetText(L " Paste " );
149 buttonPaste -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
150 buttonPaste -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonPaste_OnClicked);
151 item -> AddChild(buttonPaste -> GetBoundsComposition());
152 }
153 {
154 GuiStackItemComposition * item = new GuiStackItemComposition;
155 stack -> AddChild(item);
156
157 buttonSelectAll = g::NewButton();
158 buttonSelectAll -> SetText(L " Select All " );
159 buttonSelectAll -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
160 buttonSelectAll -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonSelectAll_OnClicked);
161 item -> AddChild(buttonSelectAll -> GetBoundsComposition());
162 }
163 {
164 GuiStackItemComposition * item = new GuiStackItemComposition;
165 stack -> AddChild(item);
166
167 checkReadonly = g::NewCheckBox();
168 checkReadonly -> SetText(L " Readonly " );
169 checkReadonly -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
170 checkReadonly -> SelectedChanged.AttachMethod( this , & TextBoxEditorWindow::checkReadonly_OnSelectedChanged);
171 item -> AddChild(checkReadonly -> GetBoundsComposition());
172 }
173 }
174 {
175 GuiCellComposition * cell = new GuiCellComposition;
176 table -> AddChild(cell);
177 cell -> SetSite( 1 , 0 , 1 , 1 );
178
179 GuiStackComposition * stack = new GuiStackComposition;
180 stack -> SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
181 stack -> SetPadding( 2 );
182 stack -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
183 cell -> AddChild(stack);
184
185 {
186 GuiStackItemComposition * item = new GuiStackItemComposition;
187 stack -> AddChild(item);
188
189 textGoto = g::NewTextBox();
190 textGoto -> GetBoundsComposition() -> SetBounds(Rect(Point( 0 , 0 ), Size( 180 , 0 )));
191 textGoto -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
192 textGoto -> TextChanged.AttachMethod( this , & TextBoxEditorWindow::textGoto_TextChanged);
193 item -> AddChild(textGoto -> GetBoundsComposition());
194 }
195 {
196 GuiStackItemComposition * item = new GuiStackItemComposition;
197 stack -> AddChild(item);
198
199 buttonGoto = g::NewButton();
200 buttonGoto -> SetText(L " Go to this line " );
201 buttonGoto -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
202 buttonGoto -> Clicked.AttachMethod( this , & TextBoxEditorWindow::buttonGoto_OnClicked);
203 item -> AddChild(buttonGoto -> GetBoundsComposition());
204 }
205 }
206 {
207 GuiCellComposition * cell = new GuiCellComposition;
208 table -> AddChild(cell);
209 cell -> SetSite( 2 , 0 , 1 , 1 );
210
211 textDocument = g::NewMultilineTextBox();
212 textDocument -> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 , 0 , 0 , 0 ));
213 textDocument -> SelectionChanged.AttachMethod( this , & TextBoxEditorWindow::textDocument_SelectionChanged);
214 cell -> AddChild(textDocument -> GetBoundsComposition());
215 }
216
217 // make some buttons enabled or disabled appropiately
218 UpdateEditButtonState();
219 UpdateGotoButtonState();
220 // set the preferred minimum client size
221 this -> GetBoundsComposition() -> SetPreferredMinSize(Size( 640 , 480 ));
222 // call this to calculate the size immediately if any indirect content in the table changes
223 // so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
224 this -> ForceCalculateSizeImmediately();
225 // move to the screen center
226 this -> MoveToScreenCenter();
227 }
228
229 ~ TextBoxEditorWindow()
230 {
231 }
232 };
233
234 void GuiMain()
235 {
236 GuiWindow * window = new TextBoxEditorWindow();
237 GetApplication() -> Run(window);
238 delete window;
239 }
GacUI将提供两个文本框的Demo,这是第一个。GacUI的文本框从一开始就具备了让每一个字符的颜色可以不同的功能,下一个Demo将展示如何利用使用正则表达式构建的词法分析器(见 这里和 这里),让文本框在编辑的时候,跟所有的代码编辑器一样,可以根据情况把不同的字符串染成不同的颜色。