Mercurial > projects > dwt-samples
annotate dwtexamples/texteditor/TextEditor.d @ 65:a84ba4d1820f
restructure the dsss.conf and resources
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Fri, 11 Apr 2008 21:15:36 +0200 |
parents | 7c3196948c7f |
children |
rev | line source |
---|---|
16 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2006 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Thomas Graber <d4rkdragon@gmail.com> | |
12 *******************************************************************************/ | |
13 module dwtexamples.texteditor.TextEditor; | |
14 | |
15 import dwt.DWT; | |
16 import dwt.custom.ExtendedModifyEvent; | |
17 import dwt.custom.ExtendedModifyListener; | |
18 import dwt.custom.StyleRange; | |
19 import dwt.custom.StyledText; | |
20 import dwt.events.DisposeEvent; | |
21 import dwt.events.DisposeListener; | |
22 import dwt.events.SelectionAdapter; | |
23 import dwt.events.SelectionEvent; | |
24 import dwt.graphics.Color; | |
25 import dwt.graphics.Font; | |
26 import dwt.graphics.FontData; | |
27 import dwt.graphics.Point; | |
28 import dwt.graphics.RGB; | |
29 import dwt.layout.GridData; | |
30 import dwt.layout.GridLayout; | |
31 import dwt.widgets.Display; | |
32 import dwt.widgets.FontDialog; | |
33 import dwt.widgets.Menu; | |
34 import dwt.widgets.MenuItem; | |
35 import dwt.widgets.Shell; | |
36 import dwt.widgets.ToolBar; | |
37 import dwt.widgets.ToolItem; | |
38 import dwt.widgets.Widget; | |
39 import dwt.dwthelper.ResourceBundle; | |
34 | 40 import dwt.dwthelper.utils; |
16 | 41 |
42 import tango.util.collection.ArraySeq; | |
43 | |
44 import dwtexamples.texteditor.Images; | |
45 | |
20 | 46 version( JIVE ){ |
47 import jive.stacktrace; | |
48 } | |
49 | |
16 | 50 /** |
51 */ | |
20 | 52 public class TextEditor { |
16 | 53 Shell shell; |
54 ToolBar toolBar; | |
55 StyledText text; | |
20 | 56 Images images; |
16 | 57 alias ArraySeq!(StyleRange) StyleCache; |
58 StyleCache cachedStyles; | |
59 | |
20 | 60 Color RED = null; |
61 Color BLUE = null; | |
62 Color GREEN = null; | |
16 | 63 Font font = null; |
64 ToolItem boldButton, italicButton, underlineButton, strikeoutButton; | |
20 | 65 |
16 | 66 //string resources |
67 static ResourceBundle resources; | |
65
a84ba4d1820f
restructure the dsss.conf and resources
Frank Benoit <benoit@tionex.de>
parents:
34
diff
changeset
|
68 private static const char[] resourceData = import( "dwtexamples.texteditor.examples_texteditor.properties" ); |
20 | 69 |
70 /* | |
16 | 71 * static ctor |
72 */ | |
73 static this() | |
74 { | |
75 resources = ResourceBundle.getBundleFromData( resourceData ); | |
76 } | |
20 | 77 |
78 /* | |
16 | 79 * ctor |
80 */ | |
81 this() { | |
82 images = new Images(); | |
83 } | |
20 | 84 |
85 /* | |
86 * creates edit menu | |
16 | 87 */ |
88 Menu createEditMenu() { | |
89 Menu bar = shell.getMenuBar (); | |
90 Menu menu = new Menu (bar); | |
20 | 91 |
16 | 92 MenuItem item = new MenuItem (menu, DWT.PUSH); |
93 item.setText (resources.getString("Cut_menuitem")); | |
94 item.setAccelerator(DWT.MOD1 + 'X'); | |
95 item.addSelectionListener(new class() SelectionAdapter { | |
96 public void widgetSelected(SelectionEvent event) { | |
97 handleCutCopy(); | |
98 text.cut(); | |
99 } | |
100 }); | |
101 item = new MenuItem (menu, DWT.PUSH); | |
102 item.setText (resources.getString("Copy_menuitem")); | |
103 item.setAccelerator(DWT.MOD1 + 'C'); | |
104 item.addSelectionListener(new class() SelectionAdapter { | |
105 public void widgetSelected(SelectionEvent event) { | |
106 handleCutCopy(); | |
107 text.copy(); | |
108 } | |
109 }); | |
110 item = new MenuItem (menu, DWT.PUSH); | |
111 item.setText (resources.getString("Paste_menuitem")); | |
112 item.setAccelerator(DWT.MOD1 + 'V'); | |
113 item.addSelectionListener(new class() SelectionAdapter { | |
114 public void widgetSelected(SelectionEvent event) { | |
115 text.paste(); | |
116 } | |
117 }); | |
20 | 118 new MenuItem (menu, DWT.SEPARATOR); |
16 | 119 item = new MenuItem (menu, DWT.PUSH); |
120 item.setText (resources.getString("Font_menuitem")); | |
121 item.addSelectionListener(new class() SelectionAdapter { | |
122 public void widgetSelected(SelectionEvent event) { | |
123 setFont(); | |
124 } | |
125 }); | |
126 return menu; | |
127 } | |
20 | 128 |
129 /* | |
130 * creates file menu | |
16 | 131 */ |
132 Menu createFileMenu() { | |
133 Menu bar = shell.getMenuBar (); | |
134 Menu menu = new Menu (bar); | |
20 | 135 |
16 | 136 MenuItem item = new MenuItem (menu, DWT.PUSH); |
137 item.setText (resources.getString("Exit_menuitem")); | |
138 item.addSelectionListener(new class() SelectionAdapter { | |
139 public void widgetSelected(SelectionEvent event) { | |
140 shell.close (); | |
141 } | |
142 }); | |
143 | |
144 return menu; | |
145 } | |
146 | |
147 /* | |
148 * Set a style | |
149 */ | |
150 void setStyle(Widget widget) { | |
151 Point sel = text.getSelectionRange(); | |
152 if ((sel is null) || (sel.y is 0)) return; | |
153 StyleRange style; | |
154 for (int i = sel.x; i<sel.x+sel.y; i++) { | |
155 StyleRange range = text.getStyleRangeAtOffset(i); | |
156 if (range !is null) { | |
157 style = cast(StyleRange)range.clone(); | |
158 style.start = i; | |
159 style.length = 1; | |
160 } else { | |
161 style = new StyleRange(i, 1, null, null, DWT.NORMAL); | |
162 } | |
163 if (widget is boldButton) { | |
164 style.fontStyle ^= DWT.BOLD; | |
165 } else if (widget is italicButton) { | |
20 | 166 style.fontStyle ^= DWT.ITALIC; |
16 | 167 } else if (widget is underlineButton) { |
168 style.underline = !style.underline; | |
169 } else if (widget is strikeoutButton) { | |
170 style.strikeout = !style.strikeout; | |
171 } | |
172 text.setStyleRange(style); | |
173 } | |
20 | 174 text.setSelectionRange(sel.x + sel.y, 0); |
16 | 175 } |
176 | |
177 /* | |
178 * Clear all style data for the selected text. | |
179 */ | |
180 void clear() { | |
181 Point sel = text.getSelectionRange(); | |
182 if (sel.y !is 0) { | |
183 StyleRange style; | |
184 style = new StyleRange(sel.x, sel.y, null, null, DWT.NORMAL); | |
185 text.setStyleRange(style); | |
186 } | |
187 text.setSelectionRange(sel.x + sel.y, 0); | |
188 } | |
20 | 189 |
16 | 190 /* |
191 * Set the foreground color for the selected text. | |
192 */ | |
193 void fgColor(Color fg) { | |
194 Point sel = text.getSelectionRange(); | |
195 if ((sel is null) || (sel.y is 0)) return; | |
196 StyleRange style, range; | |
197 for (int i = sel.x; i<sel.x+sel.y; i++) { | |
198 range = text.getStyleRangeAtOffset(i); | |
199 if (range !is null) { | |
200 style = cast(StyleRange)range.clone(); | |
201 style.start = i; | |
202 style.length = 1; | |
203 style.foreground = fg; | |
204 } else { | |
205 style = new StyleRange (i, 1, fg, null, DWT.NORMAL); | |
206 } | |
207 text.setStyleRange(style); | |
208 } | |
209 text.setSelectionRange(sel.x + sel.y, 0); | |
210 } | |
20 | 211 |
212 /* | |
16 | 213 * creates menu bar |
214 */ | |
215 void createMenuBar () { | |
216 Menu bar = new Menu (shell, DWT.BAR); | |
217 shell.setMenuBar (bar); | |
218 | |
219 MenuItem fileItem = new MenuItem (bar, DWT.CASCADE); | |
220 fileItem.setText (resources.getString("File_menuitem")); | |
221 fileItem.setMenu (createFileMenu ()); | |
222 | |
223 MenuItem editItem = new MenuItem (bar, DWT.CASCADE); | |
224 editItem.setText (resources.getString("Edit_menuitem")); | |
225 editItem.setMenu (createEditMenu ()); | |
226 } | |
20 | 227 |
228 /* | |
16 | 229 * creates shell |
230 */ | |
231 void createShell (Display display) { | |
232 shell = new Shell (display); | |
20 | 233 shell.setText (resources.getString("Window_title")); |
16 | 234 images.loadAll (display); |
235 GridLayout layout = new GridLayout(); | |
236 layout.numColumns = 1; | |
237 shell.setLayout(layout); | |
238 shell.addDisposeListener (new class() DisposeListener { | |
239 public void widgetDisposed (DisposeEvent e) { | |
240 if (font !is null) font.dispose(); | |
241 images.freeAll (); | |
242 RED.dispose(); | |
243 GREEN.dispose(); | |
244 BLUE.dispose(); | |
245 } | |
246 }); | |
247 } | |
20 | 248 |
249 /* | |
16 | 250 * creates styled text widget |
251 */ | |
252 void createStyledText() { | |
253 initializeColors(); | |
254 text = new StyledText (shell, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL | DWT.H_SCROLL); | |
255 GridData spec = new GridData(); | |
256 spec.horizontalAlignment = GridData.FILL; | |
257 spec.grabExcessHorizontalSpace = true; | |
258 spec.verticalAlignment = GridData.FILL; | |
259 spec.grabExcessVerticalSpace = true; | |
260 text.setLayoutData(spec); | |
261 text.addExtendedModifyListener(new class() ExtendedModifyListener { | |
262 public void modifyText(ExtendedModifyEvent e) { | |
263 handleExtendedModify(e); | |
264 } | |
265 }); | |
266 } | |
20 | 267 |
268 /* | |
16 | 269 * creates tool bar |
270 */ | |
271 void createToolBar() { | |
272 toolBar = new ToolBar(shell, DWT.NONE); | |
273 SelectionAdapter listener = new class() SelectionAdapter { | |
274 public void widgetSelected(SelectionEvent event) { | |
275 setStyle (event.widget); | |
276 } | |
277 }; | |
278 boldButton = new ToolItem(toolBar, DWT.CHECK); | |
279 boldButton.setImage(images.Bold); | |
280 boldButton.setToolTipText(resources.getString("Bold")); | |
281 boldButton.addSelectionListener(listener); | |
282 italicButton = new ToolItem(toolBar, DWT.CHECK); | |
283 italicButton.setImage(images.Italic); | |
284 italicButton.setToolTipText(resources.getString("Italic")); | |
285 italicButton.addSelectionListener(listener); | |
286 underlineButton = new ToolItem(toolBar, DWT.CHECK); | |
287 underlineButton.setImage(images.Underline); | |
288 underlineButton.setToolTipText(resources.getString("Underline")); | |
289 underlineButton.addSelectionListener(listener); | |
290 strikeoutButton = new ToolItem(toolBar, DWT.CHECK); | |
291 strikeoutButton.setImage(images.Strikeout); | |
292 strikeoutButton.setToolTipText(resources.getString("Strikeout")); | |
293 strikeoutButton.addSelectionListener(listener); | |
20 | 294 |
16 | 295 ToolItem item = new ToolItem(toolBar, DWT.SEPARATOR); |
296 item = new ToolItem(toolBar, DWT.PUSH); | |
297 item.setImage(images.Red); | |
298 item.addSelectionListener(new class() SelectionAdapter { | |
299 public void widgetSelected(SelectionEvent event) { | |
300 fgColor(RED); | |
301 } | |
302 }); | |
303 item = new ToolItem(toolBar, DWT.PUSH); | |
304 item.setImage(images.Green); | |
305 item.addSelectionListener(new class() SelectionAdapter { | |
306 public void widgetSelected(SelectionEvent event) { | |
307 fgColor(GREEN); | |
308 } | |
309 }); | |
310 item = new ToolItem(toolBar, DWT.PUSH); | |
311 item.setImage(images.Blue); | |
312 item.addSelectionListener(new class() SelectionAdapter { | |
313 public void widgetSelected(SelectionEvent event) { | |
314 fgColor(BLUE); | |
315 } | |
20 | 316 }); |
16 | 317 item = new ToolItem(toolBar, DWT.SEPARATOR); |
318 item = new ToolItem(toolBar, DWT.PUSH); | |
319 item.setImage(images.Erase); | |
320 item.addSelectionListener(new class() SelectionAdapter { | |
321 public void widgetSelected(SelectionEvent event) { | |
322 clear(); | |
323 } | |
324 }); | |
325 } | |
20 | 326 |
16 | 327 /* |
328 * Cache the style information for text that has been cut or copied. | |
329 */ | |
330 void handleCutCopy() { | |
331 // Save the cut/copied style info so that during paste we will maintain | |
332 // the style information. Cut/copied text is put in the clipboard in | |
20 | 333 // RTF format, but is not pasted in RTF format. The other way to |
334 // handle the pasting of styles would be to access the Clipboard directly and | |
16 | 335 // parse the RTF text. |
336 cachedStyles = new StyleCache(); | |
337 Point sel = text.getSelectionRange(); | |
338 int startX = sel.x; | |
339 for (int i=sel.x; i<=sel.x+sel.y-1; i++) { | |
340 StyleRange style = text.getStyleRangeAtOffset(i); | |
341 if (style !is null) { | |
342 style.start = style.start - startX; | |
343 if (cachedStyles.toArray().length > 0) { | |
344 StyleRange lastStyle = cachedStyles.tail(); | |
345 if (lastStyle.similarTo(style) && lastStyle.start + lastStyle.length is style.start) { | |
346 lastStyle.length++; | |
347 } else { | |
348 cachedStyles.append(style); | |
349 } | |
350 } else { | |
351 cachedStyles.append(style); | |
352 } | |
353 } | |
354 } | |
355 } | |
20 | 356 |
357 /* | |
16 | 358 * handle modify |
359 */ | |
360 void handleExtendedModify(ExtendedModifyEvent event) { | |
361 if (event.length is 0) return; | |
362 StyleRange style; | |
20 | 363 //PORTING event.length is char count, but it needs to decide on codepoint count |
364 auto cont = text.getTextRange(event.start, event.length); | |
365 if ( codepointCount(cont) is 1 || cont == text.getLineDelimiter()) { | |
16 | 366 // Have the new text take on the style of the text to its right (during |
367 // typing) if no style information is active. | |
368 int caretOffset = text.getCaretOffset(); | |
369 style = null; | |
370 if (caretOffset < text.getCharCount()) style = text.getStyleRangeAtOffset(caretOffset); | |
371 if (style !is null) { | |
372 style = cast(StyleRange) style.clone (); | |
373 style.start = event.start; | |
374 style.length = event.length; | |
375 } else { | |
376 style = new StyleRange(event.start, event.length, null, null, DWT.NORMAL); | |
20 | 377 } |
16 | 378 if (boldButton.getSelection()) style.fontStyle |= DWT.BOLD; |
379 if (italicButton.getSelection()) style.fontStyle |= DWT.ITALIC; | |
380 style.underline = underlineButton.getSelection(); | |
381 style.strikeout = strikeoutButton.getSelection(); | |
382 if (!style.isUnstyled()) text.setStyleRange(style); | |
383 } else { | |
384 // paste occurring, have text take on the styles it had when it was | |
385 // cut/copied | |
386 foreach (style; cachedStyles) { | |
387 StyleRange newStyle = cast(StyleRange)style.clone(); | |
388 newStyle.start = style.start + event.start; | |
389 text.setStyleRange(newStyle); | |
390 } | |
391 } | |
392 } | |
20 | 393 |
394 /* | |
395 * opens the shell | |
16 | 396 */ |
397 public Shell open (Display display) { | |
398 createShell (display); | |
399 createMenuBar (); | |
400 createToolBar (); | |
401 createStyledText (); | |
402 shell.setSize(500, 300); | |
403 shell.open (); | |
404 return shell; | |
405 } | |
20 | 406 |
407 /* | |
16 | 408 * set the font for styled text widget |
409 */ | |
410 void setFont() { | |
411 FontDialog fontDialog = new FontDialog(shell); | |
412 fontDialog.setFontList((text.getFont()).getFontData()); | |
413 FontData fontData = fontDialog.open(); | |
414 if (fontData !is null) { | |
20 | 415 Font newFont = new Font(shell.getDisplay(), fontData); |
16 | 416 text.setFont(newFont); |
417 if (font !is null) font.dispose(); | |
418 font = newFont; | |
419 } | |
420 } | |
20 | 421 |
422 /* | |
16 | 423 * initialize the colors |
424 */ | |
425 void initializeColors() { | |
426 Display display = Display.getDefault(); | |
427 RED = new Color (display, new RGB(255,0,0)); | |
428 BLUE = new Color (display, new RGB(0,0,255)); | |
429 GREEN = new Color (display, new RGB(0,255,0)); | |
430 } | |
431 } | |
432 | |
20 | 433 /* |
16 | 434 * main function |
435 */ | |
436 public void main (char[][] args) { | |
437 Display display = new Display (); | |
438 TextEditor example = new TextEditor (); | |
439 Shell shell = example.open (display); | |
440 while (!shell.isDisposed ()) | |
441 if (!display.readAndDispatch ()) display.sleep (); | |
442 display.dispose (); | |
443 } |