Mercurial > projects > dwt-addons
comparison dwtx/ui/internal/forms/MessageManager.d @ 75:5d489b9f966c
Fix continue porting
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 24 May 2008 05:11:16 +0200 |
parents | |
children | e193036d82c9 |
comparison
equal
deleted
inserted
replaced
74:dad2e11b8ae4 | 75:5d489b9f966c |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2007 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 * Frank Benoit <benoit@tionex.de> | |
12 ******************************************************************************/ | |
13 | |
14 module dwtx.ui.internal.forms.MessageManager; | |
15 | |
16 import dwtx.ui.internal.forms.Messages; | |
17 | |
18 import dwt.DWT; | |
19 import dwt.custom.CLabel; | |
20 import dwt.widgets.Composite; | |
21 import dwt.widgets.Control; | |
22 import dwt.widgets.Label; | |
23 import dwtx.jface.dialogs.IMessageProvider; | |
24 import dwtx.jface.fieldassist.ControlDecoration; | |
25 import dwtx.jface.fieldassist.FieldDecoration; | |
26 import dwtx.jface.fieldassist.FieldDecorationRegistry; | |
27 import dwtx.ui.forms.IMessage; | |
28 import dwtx.ui.forms.IMessageManager; | |
29 import dwtx.ui.forms.IMessagePrefixProvider; | |
30 import dwtx.ui.forms.widgets.Hyperlink; | |
31 import dwtx.ui.forms.widgets.ScrolledForm; | |
32 | |
33 import dwt.dwthelper.utils; | |
34 | |
35 import tango.util.collection.ArraySeq; | |
36 import tango.util.collection.HashMap; | |
37 import tango.util.Convert; | |
38 | |
39 /** | |
40 * @see IMessageManager | |
41 */ | |
42 | |
43 public class MessageManager : IMessageManager { | |
44 | |
45 private static final DefaultPrefixProvider DEFAULT_PREFIX_PROVIDER_; | |
46 private static final DefaultPrefixProvider DEFAULT_PREFIX_PROVIDER(){ | |
47 if( DEFAULT_PREFIX_PROVIDER_ is null ){ | |
48 synchronized(MessageManager.classinfo){ | |
49 if( DEFAULT_PREFIX_PROVIDER_ is null ){ | |
50 DEFAULT_PREFIX_PROVIDER_ = new DefaultPrefixProvider(); | |
51 } | |
52 } | |
53 } | |
54 return DEFAULT_PREFIX_PROVIDER_; | |
55 } | |
56 private ArraySeq!(Object) messages; | |
57 private HashMap!(Object,Object) decorators; | |
58 private bool autoUpdate = true; | |
59 private ScrolledForm scrolledForm; | |
60 private IMessagePrefixProvider prefixProvider; | |
61 private int decorationPosition = DWT.LEFT | DWT.BOTTOM; | |
62 | |
63 private static FieldDecoration standardError_; | |
64 private static FieldDecoration standardError(){ | |
65 if( standardError_ is null ){ | |
66 synchronized(MessageManager.classinfo){ | |
67 if( standardError_ is null ){ | |
68 standardError_ = FieldDecorationRegistry | |
69 .getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); | |
70 } | |
71 } | |
72 } | |
73 return standardError_; | |
74 } | |
75 | |
76 private static FieldDecoration standardWarning_; | |
77 private static FieldDecoration standardWarning(){ | |
78 if( standardWarning_ is null ){ | |
79 synchronized(MessageManager.classinfo){ | |
80 if( standardWarning_ is null ){ | |
81 standardWarning_ = FieldDecorationRegistry | |
82 .getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); | |
83 } | |
84 } | |
85 } | |
86 return standardWarning_; | |
87 } | |
88 | |
89 private static FieldDecoration standardInformation_; | |
90 private static FieldDecoration standardInformation(){ | |
91 if( standardInformation_ is null ){ | |
92 synchronized(MessageManager.classinfo){ | |
93 if( standardInformation_ is null ){ | |
94 standardInformation_ = FieldDecorationRegistry | |
95 .getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION); | |
96 } | |
97 } | |
98 } | |
99 return standardInformation_; | |
100 } | |
101 | |
102 private static const String[] SINGLE_MESSAGE_SUMMARY_KEYS = [ | |
103 Messages.MessageManager_sMessageSummary, | |
104 Messages.MessageManager_sMessageSummary, | |
105 Messages.MessageManager_sWarningSummary, | |
106 Messages.MessageManager_sErrorSummary ]; | |
107 | |
108 private static const String[] MULTIPLE_MESSAGE_SUMMARY_KEYS = [ | |
109 Messages.MessageManager_pMessageSummary, | |
110 Messages.MessageManager_pMessageSummary, | |
111 Messages.MessageManager_pWarningSummary, | |
112 Messages.MessageManager_pErrorSummary ]; | |
113 | |
114 static class Message : IMessage { | |
115 Control control; | |
116 Object data; | |
117 Object key; | |
118 String message; | |
119 int type; | |
120 String prefix; | |
121 | |
122 this(Object key, String message, int type, Object data) { | |
123 this.key = key; | |
124 this.message = message; | |
125 this.type = type; | |
126 this.data = data; | |
127 } | |
128 | |
129 /* | |
130 * (non-Javadoc) | |
131 * | |
132 * @see dwtx.jface.dialogs.IMessage#getKey() | |
133 */ | |
134 public Object getKey() { | |
135 return key; | |
136 } | |
137 | |
138 /* | |
139 * (non-Javadoc) | |
140 * | |
141 * @see dwtx.jface.dialogs.IMessageProvider#getMessage() | |
142 */ | |
143 public String getMessage() { | |
144 return message; | |
145 } | |
146 | |
147 /* | |
148 * (non-Javadoc) | |
149 * | |
150 * @see dwtx.jface.dialogs.IMessageProvider#getMessageType() | |
151 */ | |
152 public int getMessageType() { | |
153 return type; | |
154 } | |
155 | |
156 /* | |
157 * (non-Javadoc) | |
158 * | |
159 * @see dwtx.ui.forms.messages.IMessage#getControl() | |
160 */ | |
161 public Control getControl() { | |
162 return control; | |
163 } | |
164 | |
165 /* | |
166 * (non-Javadoc) | |
167 * | |
168 * @see dwtx.ui.forms.messages.IMessage#getData() | |
169 */ | |
170 public Object getData() { | |
171 return data; | |
172 } | |
173 | |
174 /* | |
175 * (non-Javadoc) | |
176 * | |
177 * @see dwtx.ui.forms.messages.IMessage#getPrefix() | |
178 */ | |
179 public String getPrefix() { | |
180 return prefix; | |
181 } | |
182 } | |
183 | |
184 static class DefaultPrefixProvider : IMessagePrefixProvider { | |
185 | |
186 public String getPrefix(Control c) { | |
187 Composite parent = c.getParent(); | |
188 Control[] siblings = parent.getChildren(); | |
189 for (int i = 0; i < siblings.length; i++) { | |
190 if (siblings[i] is c) { | |
191 // this is us - go backward until you hit | |
192 // a label-like widget | |
193 for (int j = i - 1; j >= 0; j--) { | |
194 Control label = siblings[j]; | |
195 String ltext = null; | |
196 if ( auto l = cast(Label)label ) { | |
197 ltext = l.getText(); | |
198 } else if ( auto hl = cast(Hyperlink)label ) { | |
199 ltext = hl.getText(); | |
200 } else if ( auto cl = cast(CLabel)label ) { | |
201 ltext = cl.getText(); | |
202 } | |
203 if (ltext !is null) { | |
204 if (!ltext.endsWith(":")) //$NON-NLS-1$ | |
205 return ltext ~ ": "; //$NON-NLS-1$ | |
206 return ltext ~ " "; //$NON-NLS-1$ | |
207 } | |
208 } | |
209 break; | |
210 } | |
211 } | |
212 return null; | |
213 } | |
214 } | |
215 | |
216 class ControlDecorator { | |
217 private ControlDecoration decoration; | |
218 private ArraySeq!(Message) controlMessages = new ArraySeq!(Message); | |
219 private String prefix; | |
220 | |
221 this(Control control) { | |
222 this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody()); | |
223 } | |
224 | |
225 public bool isDisposed() { | |
226 return decoration.getControl() is null; | |
227 } | |
228 | |
229 void updatePrefix() { | |
230 prefix = null; | |
231 } | |
232 | |
233 void updatePosition() { | |
234 Control control = decoration.getControl(); | |
235 decoration.dispose(); | |
236 this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody()); | |
237 update(); | |
238 } | |
239 | |
240 String getPrefix() { | |
241 if (prefix is null) | |
242 createPrefix(); | |
243 return prefix; | |
244 } | |
245 | |
246 private void createPrefix() { | |
247 if (prefixProvider is null) { | |
248 prefix = ""; //$NON-NLS-1$ | |
249 return; | |
250 } | |
251 prefix = prefixProvider.getPrefix(decoration.getControl()); | |
252 if (prefix is null) | |
253 // make a prefix anyway | |
254 prefix = ""; //$NON-NLS-1$ | |
255 } | |
256 | |
257 void addAll(ArraySeq!(Object) target) { | |
258 target.addAll(controlMessages); | |
259 } | |
260 | |
261 void addMessage(Object key, String text, Object data, int type) { | |
262 Message message = this.outer.addMessage(getPrefix(), key, | |
263 text, data, type, controlMessages); | |
264 message.control = decoration.getControl(); | |
265 if (isAutoUpdate()) | |
266 update(); | |
267 } | |
268 | |
269 bool removeMessage(Object key) { | |
270 Message message = findMessage(key, controlMessages); | |
271 if (message !is null) { | |
272 controlMessages.remove(message); | |
273 if (isAutoUpdate()) | |
274 update(); | |
275 } | |
276 return message !is null; | |
277 } | |
278 | |
279 bool removeMessages() { | |
280 if (controlMessages.isEmpty()) | |
281 return false; | |
282 controlMessages.clear(); | |
283 if (isAutoUpdate()) | |
284 update(); | |
285 return true; | |
286 } | |
287 | |
288 public void update() { | |
289 if (controlMessages.isEmpty()) { | |
290 decoration.setDescriptionText(null); | |
291 decoration.hide(); | |
292 } else { | |
293 auto peers = createPeers(controlMessages); | |
294 int type = (cast(IMessage) peers.get(0)).getMessageType(); | |
295 String description = createDetails(createPeers(peers), true); | |
296 if (type is IMessageProvider.ERROR) | |
297 decoration.setImage(standardError.getImage()); | |
298 else if (type is IMessageProvider.WARNING) | |
299 decoration.setImage(standardWarning.getImage()); | |
300 else if (type is IMessageProvider.INFORMATION) | |
301 decoration.setImage(standardInformation.getImage()); | |
302 decoration.setDescriptionText(description); | |
303 decoration.show(); | |
304 } | |
305 } | |
306 } | |
307 | |
308 /** | |
309 * Creates a new instance of the message manager that will work with the | |
310 * provided form. | |
311 * | |
312 * @param scrolledForm | |
313 * the form to control | |
314 */ | |
315 public this(ScrolledForm scrolledForm) { | |
316 prefixProvider = DEFAULT_PREFIX_PROVIDER; | |
317 messages = new ArraySeq!(Object); | |
318 decorators = new HashMap!(Object,Object); | |
319 this.scrolledForm = scrolledForm; | |
320 } | |
321 | |
322 /* | |
323 * (non-Javadoc) | |
324 * | |
325 * @see dwtx.ui.forms.IMessageManager#addMessage(java.lang.Object, | |
326 * java.lang.String, int) | |
327 */ | |
328 public void addMessage(Object key, String messageText, Object data, int type) { | |
329 addMessage(null, key, messageText, data, type, messages); | |
330 if (isAutoUpdate()) | |
331 updateForm(); | |
332 } | |
333 | |
334 /* | |
335 * (non-Javadoc) | |
336 * | |
337 * @see dwtx.ui.forms.IMessageManager#addMessage(java.lang.Object, | |
338 * java.lang.String, int, dwt.widgets.Control) | |
339 */ | |
340 public void addMessage(Object key, String messageText, Object data, | |
341 int type, Control control) { | |
342 ControlDecorator dec = cast(ControlDecorator) decorators.get(control); | |
343 | |
344 if (dec is null) { | |
345 dec = new ControlDecorator(control); | |
346 decorators.put(control, dec); | |
347 } | |
348 dec.addMessage(key, messageText, data, type); | |
349 if (isAutoUpdate()) | |
350 updateForm(); | |
351 } | |
352 | |
353 /* | |
354 * (non-Javadoc) | |
355 * | |
356 * @see dwtx.ui.forms.IMessageManager#removeMessage(java.lang.Object) | |
357 */ | |
358 public void removeMessage(Object key) { | |
359 Message message = findMessage(key, messages); | |
360 if (message !is null) { | |
361 messages.remove(message); | |
362 if (isAutoUpdate()) | |
363 updateForm(); | |
364 } | |
365 } | |
366 | |
367 /* | |
368 * (non-Javadoc) | |
369 * | |
370 * @see dwtx.ui.forms.IMessageManager#removeMessages() | |
371 */ | |
372 public void removeMessages() { | |
373 if (!messages.isEmpty()) { | |
374 messages.clear(); | |
375 if (isAutoUpdate()) | |
376 updateForm(); | |
377 } | |
378 } | |
379 | |
380 /* | |
381 * (non-Javadoc) | |
382 * | |
383 * @see dwtx.ui.forms.IMessageManager#removeMessage(java.lang.Object, | |
384 * dwt.widgets.Control) | |
385 */ | |
386 public void removeMessage(Object key, Control control) { | |
387 ControlDecorator dec = cast(ControlDecorator) decorators.get(control); | |
388 if (dec is null) | |
389 return; | |
390 if (dec.removeMessage(key)) | |
391 if (isAutoUpdate()) | |
392 updateForm(); | |
393 } | |
394 | |
395 /* | |
396 * (non-Javadoc) | |
397 * | |
398 * @see dwtx.ui.forms.IMessageManager#removeMessages(dwt.widgets.Control) | |
399 */ | |
400 public void removeMessages(Control control) { | |
401 ControlDecorator dec = cast(ControlDecorator) decorators.get(control); | |
402 if (dec !is null) { | |
403 if (dec.removeMessages()) { | |
404 if (isAutoUpdate()) | |
405 updateForm(); | |
406 } | |
407 } | |
408 } | |
409 | |
410 /* | |
411 * (non-Javadoc) | |
412 * | |
413 * @see dwtx.ui.forms.IMessageManager#removeAllMessages() | |
414 */ | |
415 public void removeAllMessages() { | |
416 bool needsUpdate = false; | |
417 for (Enumeration enm = decorators.elements(); enm.hasMoreElements();) { | |
418 ControlDecorator control = cast(ControlDecorator) enm.nextElement(); | |
419 if (control.removeMessages()) | |
420 needsUpdate = true; | |
421 } | |
422 if (!messages.isEmpty()) { | |
423 messages.clear(); | |
424 needsUpdate = true; | |
425 } | |
426 if (needsUpdate && isAutoUpdate()) | |
427 updateForm(); | |
428 } | |
429 | |
430 /* | |
431 * Adds the message if it does not already exist in the provided list. | |
432 */ | |
433 | |
434 private Message addMessage(String prefix, Object key, String messageText, | |
435 Object data, int type, ArraySeq!(Object) list) { | |
436 Message message = findMessage(key, list); | |
437 if (message is null) { | |
438 message = new Message(key, messageText, type, data); | |
439 message.prefix = prefix; | |
440 list.add(message); | |
441 } else { | |
442 message.message = messageText; | |
443 message.type = type; | |
444 message.data = data; | |
445 } | |
446 return message; | |
447 } | |
448 | |
449 /* | |
450 * Finds the message with the provided key in the provided list. | |
451 */ | |
452 | |
453 private Message findMessage(Object key, ArraySeq!(Object) list) { | |
454 for (int i = 0; i < list.size(); i++) { | |
455 Message message = cast(Message) list.get(i); | |
456 if (message.getKey().equals(key)) | |
457 return message; | |
458 } | |
459 return null; | |
460 } | |
461 | |
462 /* | |
463 * (non-Javadoc) | |
464 * | |
465 * @see dwtx.ui.forms.IMessageManager#update() | |
466 */ | |
467 public void update() { | |
468 // Update decorations | |
469 for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { | |
470 ControlDecorator dec = cast(ControlDecorator) iter.next(); | |
471 dec.update(); | |
472 } | |
473 // Update the form | |
474 updateForm(); | |
475 } | |
476 | |
477 /* | |
478 * Updates the container by rolling the messages up from the controls. | |
479 */ | |
480 | |
481 private void updateForm() { | |
482 ArrayList mergedList = new ArrayList(); | |
483 mergedList.addAll(messages); | |
484 for (Enumeration enm = decorators.elements(); enm.hasMoreElements();) { | |
485 ControlDecorator dec = cast(ControlDecorator) enm.nextElement(); | |
486 dec.addAll(mergedList); | |
487 } | |
488 update(mergedList); | |
489 } | |
490 | |
491 private void update(ArraySeq!(Object) mergedList) { | |
492 pruneControlDecorators(); | |
493 if (scrolledForm.getForm().getHead().getBounds().height is 0 || mergedList.isEmpty() || mergedList is null) { | |
494 scrolledForm.setMessage(null, IMessageProvider.NONE); | |
495 return; | |
496 } | |
497 auto peers = createPeers(mergedList); | |
498 int maxType = (cast(IMessage) peers.get(0)).getMessageType(); | |
499 String messageText; | |
500 IMessage[] array = arraycast!(IMessage)( peers | |
501 .toArray()); | |
502 if (peers.size() is 1 && (cast(Message) peers.get(0)).prefix is null) { | |
503 // a single message | |
504 IMessage message = cast(IMessage) peers.get(0); | |
505 messageText = message.getMessage(); | |
506 scrolledForm.setMessage(messageText, maxType, array); | |
507 } else { | |
508 // show a summary message for the message | |
509 // and list of errors for the details | |
510 if (peers.size() > 1) | |
511 messageText = Messages.bind( | |
512 MULTIPLE_MESSAGE_SUMMARY_KEYS[maxType], | |
513 [ to!(String)(peers.size()) ]); //$NON-NLS-1$ | |
514 else | |
515 messageText = SINGLE_MESSAGE_SUMMARY_KEYS[maxType]; | |
516 scrolledForm.setMessage(messageText, maxType, array); | |
517 } | |
518 } | |
519 | |
520 private static String getFullMessage(IMessage message) { | |
521 if (message.getPrefix() is null) | |
522 return message.getMessage(); | |
523 return message.getPrefix() + message.getMessage(); | |
524 } | |
525 | |
526 private ArraySeq!(Message) createPeers(ArraySeq!(Message) messages) { | |
527 auto peers = new ArraySeq!(Message); | |
528 int maxType = 0; | |
529 foreach( message; messages ){ | |
530 if (message.type > maxType) { | |
531 peers.clear(); | |
532 maxType = message.type; | |
533 } | |
534 if (message.type is maxType) | |
535 peers.append(message); | |
536 } | |
537 return peers; | |
538 } | |
539 | |
540 private String createDetails(ArraySeq!(Object) messages, bool excludePrefix) { | |
541 StringWriter sw = new StringWriter(); | |
542 PrintWriter out_ = new PrintWriter(sw); | |
543 | |
544 for (int i = 0; i < messages.size(); i++) { | |
545 if (i > 0) | |
546 out_.println(); | |
547 IMessage m = cast(IMessage) messages.get(i); | |
548 out_.print(excludePrefix ? m.getMessage() : getFullMessage(m)); | |
549 } | |
550 out_.flush(); | |
551 return sw.toString(); | |
552 } | |
553 | |
554 public static String createDetails(IMessage[] messages) { | |
555 if (messages is null || messages.length is 0) | |
556 return null; | |
557 StringWriter sw = new StringWriter(); | |
558 PrintWriter out_ = new PrintWriter(sw); | |
559 | |
560 for (int i = 0; i < messages.length; i++) { | |
561 if (i > 0) | |
562 out_.println(); | |
563 out_.print(getFullMessage(messages[i])); | |
564 } | |
565 out_.flush(); | |
566 return sw.toString(); | |
567 } | |
568 | |
569 /* | |
570 * (non-Javadoc) | |
571 * | |
572 * @see dwtx.ui.forms.IMessageManager#createSummary(dwtx.ui.forms.IMessage[]) | |
573 */ | |
574 public String createSummary(IMessage[] messages) { | |
575 return createDetails(messages); | |
576 } | |
577 | |
578 private void pruneControlDecorators() { | |
579 for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { | |
580 ControlDecorator dec = cast(ControlDecorator) iter.next(); | |
581 if (dec.isDisposed()) | |
582 iter.remove(); | |
583 } | |
584 } | |
585 | |
586 /* | |
587 * (non-Javadoc) | |
588 * | |
589 * @see dwtx.ui.forms.IMessageManager#getMessagePrefixProvider() | |
590 */ | |
591 public IMessagePrefixProvider getMessagePrefixProvider() { | |
592 return prefixProvider; | |
593 } | |
594 | |
595 /* | |
596 * (non-Javadoc) | |
597 * | |
598 * @see dwtx.ui.forms.IMessageManager#setMessagePrefixProvider(dwtx.ui.forms.IMessagePrefixProvider) | |
599 */ | |
600 public void setMessagePrefixProvider(IMessagePrefixProvider provider) { | |
601 this.prefixProvider = provider; | |
602 for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { | |
603 ControlDecorator dec = cast(ControlDecorator) iter.next(); | |
604 dec.updatePrefix(); | |
605 } | |
606 } | |
607 | |
608 /* | |
609 * (non-Javadoc) | |
610 * | |
611 * @see dwtx.ui.forms.IMessageManager#getDecorationPosition() | |
612 */ | |
613 public int getDecorationPosition() { | |
614 return decorationPosition; | |
615 } | |
616 | |
617 /* | |
618 * (non-Javadoc) | |
619 * | |
620 * @see dwtx.ui.forms.IMessageManager#setDecorationPosition(int) | |
621 */ | |
622 public void setDecorationPosition(int position) { | |
623 this.decorationPosition = position; | |
624 for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { | |
625 ControlDecorator dec = cast(ControlDecorator) iter.next(); | |
626 dec.updatePosition(); | |
627 } | |
628 } | |
629 | |
630 /* | |
631 * (non-Javadoc) | |
632 * | |
633 * @see dwtx.ui.forms.IMessageManager#isAutoUpdate() | |
634 */ | |
635 public bool isAutoUpdate() { | |
636 return autoUpdate; | |
637 } | |
638 | |
639 /* | |
640 * (non-Javadoc) | |
641 * | |
642 * @see dwtx.ui.forms.IMessageManager#setAutoUpdate(bool) | |
643 */ | |
644 public void setAutoUpdate(bool autoUpdate) { | |
645 bool needsUpdate = !this.autoUpdate && autoUpdate; | |
646 this.autoUpdate = autoUpdate; | |
647 if (needsUpdate) | |
648 update(); | |
649 } | |
650 } |