KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > ide > dialogs > WelcomeEditor


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  *******************************************************************************/

11
12 package org.eclipse.ui.internal.ide.dialogs;
13
14 import java.io.IOException JavaDoc;
15 import java.io.InputStream JavaDoc;
16 import java.net.URL JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.Iterator JavaDoc;
19
20 import javax.xml.parsers.ParserConfigurationException JavaDoc;
21
22 import org.eclipse.core.resources.IMarker;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.Status;
26 import org.eclipse.jface.action.MenuManager;
27 import org.eclipse.jface.preference.JFacePreferences;
28 import org.eclipse.jface.resource.JFaceColors;
29 import org.eclipse.jface.resource.JFaceResources;
30 import org.eclipse.jface.util.IPropertyChangeListener;
31 import org.eclipse.jface.util.PropertyChangeEvent;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.custom.CLabel;
34 import org.eclipse.swt.custom.ScrolledComposite;
35 import org.eclipse.swt.custom.StyleRange;
36 import org.eclipse.swt.custom.StyledText;
37 import org.eclipse.swt.events.DisposeEvent;
38 import org.eclipse.swt.events.DisposeListener;
39 import org.eclipse.swt.events.FocusAdapter;
40 import org.eclipse.swt.events.FocusEvent;
41 import org.eclipse.swt.events.KeyEvent;
42 import org.eclipse.swt.events.KeyListener;
43 import org.eclipse.swt.events.MouseAdapter;
44 import org.eclipse.swt.events.MouseEvent;
45 import org.eclipse.swt.events.MouseMoveListener;
46 import org.eclipse.swt.events.SelectionAdapter;
47 import org.eclipse.swt.events.SelectionEvent;
48 import org.eclipse.swt.events.TraverseEvent;
49 import org.eclipse.swt.events.TraverseListener;
50 import org.eclipse.swt.graphics.Color;
51 import org.eclipse.swt.graphics.Cursor;
52 import org.eclipse.swt.graphics.GC;
53 import org.eclipse.swt.graphics.Point;
54 import org.eclipse.swt.graphics.Rectangle;
55 import org.eclipse.swt.layout.GridData;
56 import org.eclipse.swt.layout.GridLayout;
57 import org.eclipse.swt.widgets.Composite;
58 import org.eclipse.swt.widgets.Display;
59 import org.eclipse.swt.widgets.Event;
60 import org.eclipse.swt.widgets.Label;
61 import org.eclipse.swt.widgets.Listener;
62 import org.eclipse.ui.IEditorInput;
63 import org.eclipse.ui.IEditorSite;
64 import org.eclipse.ui.PartInitException;
65 import org.eclipse.ui.PlatformUI;
66 import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;
67 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
68 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
69 import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
70 import org.eclipse.ui.part.EditorPart;
71 import org.xml.sax.SAXException JavaDoc;
72
73 /**
74  * A "fake" editor to show a welcome page
75  * The contents of this page are supplied in the product configuration
76  *
77  * PRIVATE
78  * This class is internal to the workbench and must not be called outside the workbench
79  */

80 public class WelcomeEditor extends EditorPart {
81
82     private final static int HORZ_SCROLL_INCREMENT = 20;
83
84     private final static int VERT_SCROLL_INCREMENT = 20;
85
86     // width at which wrapping will stop and a horizontal scroll bar will be
87
// introduced
88
private final static int WRAP_MIN_WIDTH = 150;
89
90     private Composite editorComposite;
91
92     private Cursor handCursor;
93
94     private Cursor busyCursor;
95
96     private WelcomeParser parser;
97
98     private ArrayList JavaDoc hyperlinkRanges = new ArrayList JavaDoc();
99
100     private ArrayList JavaDoc texts = new ArrayList JavaDoc();
101
102     private ScrolledComposite scrolledComposite;
103
104     private IPropertyChangeListener colorListener;
105
106     private boolean mouseDown = false;
107
108     private boolean dragEvent = false;
109
110     private StyledText firstText, lastText;
111
112     private StyledText lastNavigatedText, currentText;
113
114     private boolean nextTabAbortTraversal, previousTabAbortTraversal = false;
115
116     private WelcomeEditorCopyAction copyAction;
117
118     /**
119      * Create a new instance of the welcome editor
120      */

121     public WelcomeEditor() {
122         super();
123         setPartName(IDEWorkbenchMessages.WelcomeEditor_title);
124         copyAction = new WelcomeEditorCopyAction(this);
125         copyAction.setEnabled(false);
126     }
127
128     /**
129      * Update the welcome page to start at the
130      * beginning of the text.
131      */

132     private void focusOn(StyledText newText, int caretOffset) {
133         if (newText == null) {
134             return;
135         }
136         newText.setFocus();
137         newText.setCaretOffset(caretOffset);
138         scrolledComposite.setOrigin(0, newText.getLocation().y);
139     }
140
141     /**
142      * Finds the next text
143      */

144     private StyledText nextText(StyledText text) {
145         int index = 0;
146         if (text == null) {
147             return (StyledText) texts.get(0);
148         } else {
149             index = texts.indexOf(text);
150         }
151
152         //If we are not at the end....
153
if (index < texts.size() - 1) {
154             return (StyledText) texts.get(index + 1);
155         } else {
156             return (StyledText) texts.get(0);
157         }
158     }
159
160     /**
161      * Finds the previous text
162      */

163     private StyledText previousText(StyledText text) {
164         int index = 0;
165         if (text == null) {
166             return (StyledText) texts.get(0);
167         } else {
168             index = texts.indexOf(text);
169         }
170
171         //If we are at the beginning....
172
if (index == 0) {
173             return (StyledText) texts.get(texts.size() - 1);
174         } else {
175             return (StyledText) texts.get(index - 1);
176         }
177     }
178
179     /**
180      * Returns the current text.
181      */

182     protected StyledText getCurrentText() {
183         return currentText;
184     }
185
186     /**
187      * Returns the copy action.
188      */

189     protected WelcomeEditorCopyAction getCopyAction() {
190         return copyAction;
191     }
192
193     /**
194      * Finds the next link after the current selection.
195      */

196     private StyleRange findNextLink(StyledText text) {
197         if (text == null) {
198             return null;
199         }
200
201         WelcomeItem item = (WelcomeItem) text.getData();
202         StyleRange[] ranges = text.getStyleRanges();
203         int currentSelectionEnd = text.getSelection().y;
204
205         for (int i = 0; i < ranges.length; i++) {
206             if (ranges[i].start >= currentSelectionEnd) {
207                 if (item.isLinkAt(ranges[i].start)) {
208                     return ranges[i];
209                 }
210             }
211         }
212         return null;
213     }
214
215     /**
216      * Finds the previous link before the current selection.
217      */

218     private StyleRange findPreviousLink(StyledText text) {
219         if (text == null) {
220             return null;
221         }
222
223         WelcomeItem item = (WelcomeItem) text.getData();
224         StyleRange[] ranges = text.getStyleRanges();
225         int currentSelectionStart = text.getSelection().x;
226
227         for (int i = ranges.length - 1; i > -1; i--) {
228             if ((ranges[i].start + ranges[i].length) < currentSelectionStart) {
229                 if (item.isLinkAt(ranges[i].start + ranges[i].length - 1)) {
230                     return ranges[i];
231                 }
232             }
233         }
234         return null;
235     }
236
237     /**
238      * Finds the current link of the current selection.
239      */

240     protected StyleRange getCurrentLink(StyledText text) {
241         StyleRange[] ranges = text.getStyleRanges();
242         int currentSelectionEnd = text.getSelection().y;
243         int currentSelectionStart = text.getSelection().x;
244
245         for (int i = 0; i < ranges.length; i++) {
246             if ((currentSelectionStart >= ranges[i].start)
247                     && (currentSelectionEnd <= (ranges[i].start + ranges[i].length))) {
248                 return ranges[i];
249             }
250         }
251         return null;
252     }
253
254     /**
255      * Adds listeners to the given styled text
256      */

257     private void addListeners(StyledText styledText) {
258         styledText.addMouseListener(new MouseAdapter() {
259             public void mouseDown(MouseEvent e) {
260                 if (e.button != 1) {
261                     return;
262                 }
263                 mouseDown = true;
264             }
265
266             public void mouseUp(MouseEvent e) {
267                 mouseDown = false;
268                 StyledText text = (StyledText) e.widget;
269                 WelcomeItem item = (WelcomeItem) e.widget.getData();
270                 int offset = text.getCaretOffset();
271                 if (dragEvent) {
272                     dragEvent = false;
273                     if (item.isLinkAt(offset)) {
274                         text.setCursor(handCursor);
275                     }
276                 } else if (item.isLinkAt(offset)) {
277                     text.setCursor(busyCursor);
278                     if (e.button == 1) {
279                         item.triggerLinkAt(offset);
280                         StyleRange selectionRange = getCurrentLink(text);
281                         text.setSelectionRange(selectionRange.start,
282                                 selectionRange.length);
283                         text.setCursor(null);
284                     }
285                 }
286             }
287         });
288
289         styledText.addMouseMoveListener(new MouseMoveListener() {
290             public void mouseMove(MouseEvent e) {
291                 // Do not change cursor on drag events
292
if (mouseDown) {
293                     if (!dragEvent) {
294                         StyledText text = (StyledText) e.widget;
295                         text.setCursor(null);
296                     }
297                     dragEvent = true;
298                     return;
299                 }
300                 StyledText text = (StyledText) e.widget;
301                 WelcomeItem item = (WelcomeItem) e.widget.getData();
302                 int offset = -1;
303                 try {
304                     offset = text.getOffsetAtLocation(new Point(e.x, e.y));
305                 } catch (IllegalArgumentException JavaDoc ex) {
306                     // location is not over a character
307
}
308                 if (offset == -1) {
309                     text.setCursor(null);
310                 } else if (item.isLinkAt(offset)) {
311                     text.setCursor(handCursor);
312                 } else {
313                     text.setCursor(null);
314                 }
315             }
316         });
317
318         styledText.addTraverseListener(new TraverseListener() {
319             public void keyTraversed(TraverseEvent e) {
320                 StyledText text = (StyledText) e.widget;
321
322                 switch (e.detail) {
323                 case SWT.TRAVERSE_ESCAPE:
324                     e.doit = true;
325                     break;
326                 case SWT.TRAVERSE_TAB_NEXT:
327                     // Handle Ctrl-Tab
328
if ((e.stateMask & SWT.CTRL) != 0) {
329                         if (e.widget == lastText) {
330                             return;
331                         } else {
332                             e.doit = false;
333                             nextTabAbortTraversal = true;
334                             lastText.traverse(SWT.TRAVERSE_TAB_NEXT);
335                             return;
336                         }
337                     }
338                     if (nextTabAbortTraversal) {
339                         nextTabAbortTraversal = false;
340                         return;
341                     }
342                     // Find the next link in current widget, if applicable
343
// Stop at top of widget
344
StyleRange nextLink = findNextLink(text);
345                     if (nextLink == null) {
346                         // go to the next widget, focus at beginning
347
StyledText nextText = nextText(text);
348                         nextText.setSelection(0);
349                         focusOn(nextText, 0);
350                     } else {
351                         // focusOn: allow none tab traversals to align
352
focusOn(text, text.getSelection().x);
353                         text.setSelectionRange(nextLink.start, nextLink.length);
354                     }
355                     e.detail = SWT.TRAVERSE_NONE;
356                     e.doit = true;
357                     break;
358                 case SWT.TRAVERSE_TAB_PREVIOUS:
359                     // Handle Ctrl-Shift-Tab
360
if ((e.stateMask & SWT.CTRL) != 0) {
361                         if (e.widget == firstText) {
362                             return;
363                         } else {
364                             e.doit = false;
365                             previousTabAbortTraversal = true;
366                             firstText.traverse(SWT.TRAVERSE_TAB_PREVIOUS);
367                             return;
368                         }
369                     }
370                     if (previousTabAbortTraversal) {
371                         previousTabAbortTraversal = false;
372                         return;
373                     }
374                     // Find the previous link in current widget, if applicable
375
// Stop at top of widget also
376
StyleRange previousLink = findPreviousLink(text);
377                     if (previousLink == null) {
378                         if (text.getSelection().x == 0) {
379                             // go to the previous widget, focus at end
380
StyledText previousText = previousText(text);
381                             previousText.setSelection(previousText
382                                     .getCharCount());
383                             previousLink = findPreviousLink(previousText);
384                             if (previousLink == null) {
385                                 focusOn(previousText, 0);
386                             } else {
387                                 focusOn(previousText, previousText
388                                         .getSelection().x);
389                                 previousText
390                                         .setSelectionRange(previousLink.start,
391                                                 previousLink.length);
392                             }
393                         } else {
394                             // stay at top of this widget
395
focusOn(text, 0);
396                         }
397                     } else {
398                         // focusOn: allow none tab traversals to align
399
focusOn(text, text.getSelection().x);
400                         text.setSelectionRange(previousLink.start,
401                                 previousLink.length);
402                     }
403                     e.detail = SWT.TRAVERSE_NONE;
404                     e.doit = true;
405                     break;
406                 default:
407                     break;
408                 }
409             }
410         });
411
412         styledText.addKeyListener(new KeyListener() {
413             public void keyReleased(KeyEvent e) {
414                 //Ignore a key release
415
}
416
417             public void keyPressed(KeyEvent event) {
418                 StyledText text = (StyledText) event.widget;
419                 if (event.character == ' ' || event.character == SWT.CR) {
420                     if (text != null) {
421                         WelcomeItem item = (WelcomeItem) text.getData();
422
423                         //Be sure we are in the selection
424
int offset = text.getSelection().x + 1;
425
426                         if (item.isLinkAt(offset)) {
427                             text.setCursor(busyCursor);
428                             item.triggerLinkAt(offset);
429                             StyleRange selectionRange = getCurrentLink(text);
430                             text.setSelectionRange(selectionRange.start,
431                                     selectionRange.length);
432                             text.setCursor(null);
433                         }
434                     }
435                     return;
436                 }
437
438                 // When page down is pressed, move the cursor to the next item in the
439
// welcome page. Note that this operation wraps (pages to the top item
440
// when the last item is reached).
441
if (event.keyCode == SWT.PAGE_DOWN) {
442                     focusOn(nextText(text), 0);
443                     return;
444                 }
445
446                 // When page up is pressed, move the cursor to the previous item in the
447
// welcome page. Note that this operation wraps (pages to the bottom item
448
// when the first item is reached).
449
if (event.keyCode == SWT.PAGE_UP) {
450                     focusOn(previousText(text), 0);
451                     return;
452                 }
453             }
454         });
455
456         styledText.addFocusListener(new FocusAdapter() {
457             public void focusLost(FocusEvent e) {
458                 // Remember current text widget
459
lastNavigatedText = (StyledText) e.widget;
460             }
461
462             public void focusGained(FocusEvent e) {
463                 currentText = (StyledText) e.widget;
464
465                 // Remove highlighted selection if text widget has changed
466
if ((currentText != lastNavigatedText)
467                         && (lastNavigatedText != null)) {
468                     lastNavigatedText.setSelection(lastNavigatedText
469                             .getSelection().x);
470                 }
471
472                 // enable/disable copy action
473
copyAction.setEnabled(currentText.getSelectionCount() > 0);
474             }
475         });
476
477         styledText.addSelectionListener(new SelectionAdapter() {
478             public void widgetSelected(SelectionEvent e) {
479                 // enable/disable copy action
480
StyledText text = (StyledText) e.widget;
481                 copyAction.setEnabled(text.getSelectionCount() > 0);
482             }
483         });
484     }
485
486     /**
487      * Creates the wizard's title area.
488      *
489      * @param parent the SWT parent for the title area composite
490      * @return the created info area composite
491      */

492     private Composite createInfoArea(Composite parent) {
493         // Create the title area which will contain
494
// a title, message, and image.
495
this.scrolledComposite = new ScrolledComposite(parent, SWT.V_SCROLL
496                 | SWT.H_SCROLL);
497         this.scrolledComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
498         final Composite infoArea = new Composite(this.scrolledComposite,
499                 SWT.NONE);
500         GridLayout layout = new GridLayout();
501         layout.marginHeight = 10;
502         layout.verticalSpacing = 5;
503         layout.numColumns = 2;
504         infoArea.setLayout(layout);
505         GridData data = new GridData(GridData.FILL_BOTH);
506         infoArea.setLayoutData(data);
507         boolean wrapped = parser.isFormatWrapped();
508         int HINDENT = 20;
509
510         // Get the background color for the title area
511
Display display = parent.getDisplay();
512         Color background = JFaceColors.getBannerBackground(display);
513         Color foreground = JFaceColors.getBannerForeground(display);
514         infoArea.setBackground(background);
515
516         int textStyle = SWT.MULTI | SWT.READ_ONLY;
517         if (wrapped) {
518             textStyle = textStyle | SWT.WRAP;
519         }
520         StyledText sampleStyledText = null;
521         // Create the intro item
522
WelcomeItem item = getIntroItem();
523         if (item != null) {
524             StyledText styledText = new StyledText(infoArea, textStyle);
525             this.texts.add(styledText);
526             sampleStyledText = styledText;
527             styledText.setCursor(null);
528             JFaceColors.setColors(styledText, foreground, background);
529             styledText.setText(getIntroItem().getText());
530             setBoldRanges(styledText, item.getBoldRanges());
531             setLinkRanges(styledText, item.getActionRanges());
532             setLinkRanges(styledText, item.getHelpRanges());
533             GridData gd = new GridData(GridData.FILL_HORIZONTAL);
534             gd.horizontalSpan = 2;
535             gd.horizontalIndent = HINDENT;
536             gd.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING;
537             styledText.setLayoutData(gd);
538             styledText.setData(item);
539             addListeners(styledText);
540
541             Label spacer = new Label(infoArea, SWT.NONE);
542             spacer.setBackground(background);
543             gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
544             gd.horizontalSpan = 2;
545             spacer.setLayoutData(gd);
546         }
547         firstText = sampleStyledText;
548
549         // Create the welcome items
550
Label imageLabel = null;
551         WelcomeItem[] items = getItems();
552         for (int i = 0; i < items.length; i++) {
553             Label label = new Label(infoArea, SWT.NONE);
554             label.setBackground(background);
555             label
556                     .setImage(PlatformUI
557                             .getWorkbench()
558                             .getSharedImages()
559                             .getImage(
560                                     IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM));
561             GridData gd = new GridData();
562             gd.horizontalIndent = HINDENT;
563             gd.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING;
564             label.setLayoutData(gd);
565             if (imageLabel == null) {
566                 imageLabel = label;
567             }
568
569             StyledText styledText = new StyledText(infoArea, textStyle);
570             this.texts.add(styledText);
571             sampleStyledText = styledText;
572             styledText.setCursor(null);
573             JFaceColors.setColors(styledText, foreground, background);
574             styledText.setText(items[i].getText());
575             setBoldRanges(styledText, items[i].getBoldRanges());
576             setLinkRanges(styledText, items[i].getActionRanges());
577             setLinkRanges(styledText, items[i].getHelpRanges());
578             gd = new GridData(GridData.FILL_HORIZONTAL);
579             gd.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING;
580             gd.verticalSpan = 2;
581             styledText.setLayoutData(gd);
582             styledText.setData(items[i]);
583             addListeners(styledText);
584
585             Label spacer = new Label(infoArea, SWT.NONE);
586             spacer.setBackground(background);
587             gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
588             gd.horizontalSpan = 2;
589             spacer.setLayoutData(gd);
590
591             // create context menu
592
MenuManager menuMgr = new MenuManager("#PopUp"); //$NON-NLS-1$
593
menuMgr.add(copyAction);
594             styledText.setMenu(menuMgr.createContextMenu(styledText));
595         }
596
597         lastText = sampleStyledText;
598         this.scrolledComposite.setContent(infoArea);
599         Point p = infoArea.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
600         this.scrolledComposite.setMinHeight(p.y);
601         if (wrapped) {
602             // introduce a horizontal scroll bar after a minimum width is reached
603
this.scrolledComposite.setMinWidth(WRAP_MIN_WIDTH);
604         } else {
605             this.scrolledComposite.setMinWidth(p.x);
606         }
607         this.scrolledComposite.setExpandHorizontal(true);
608         this.scrolledComposite.setExpandVertical(true);
609
610         // When the welcome editor is resized, we need to set the width hint for
611
// wrapped StyledText widgets so that the wrapped height will be recalculated.
612
if (wrapped && (imageLabel != null)) {
613             // figure out how wide the StyledText widgets should be, do this by first
614
// calculating the width of the area not used by styled text widgets
615
Rectangle bounds = imageLabel.getBounds();
616             final int adjust = HINDENT + bounds.width + layout.verticalSpacing
617                     + (layout.marginWidth * 2);
618             final int adjustFirst = HINDENT + (layout.marginWidth * 2);
619             infoArea.addListener(SWT.Resize, new Listener() {
620                 public void handleEvent(Event event) {
621                     int w = scrolledComposite.getClientArea().width;
622                     // if the horizontal scroll bar exists, we want to wrap to the
623
// minimum wrap width
624
if (w < WRAP_MIN_WIDTH) {
625                         w = WRAP_MIN_WIDTH;
626                     }
627                     for (int i = 0; i < texts.size(); i++) {
628                         int extent;
629                         if (i == 0) {
630                             extent = w - adjustFirst;
631                         } else {
632                             extent = w - adjust;
633                         }
634                         StyledText text = (StyledText) texts.get(i);
635                         Point p = text.computeSize(extent, SWT.DEFAULT, false);
636                         ((GridData) text.getLayoutData()).widthHint = p.x;
637                     }
638                     // reset the scrolled composite height since the height of the
639
// styled text widgets have changed
640
Point p = infoArea.computeSize(SWT.DEFAULT, SWT.DEFAULT,
641                             true);
642                     scrolledComposite.setMinHeight(p.y);
643                 }
644             });
645         }
646
647         // Adjust the scrollbar increments
648
if (sampleStyledText == null) {
649             this.scrolledComposite.getHorizontalBar().setIncrement(
650                     HORZ_SCROLL_INCREMENT);
651             this.scrolledComposite.getVerticalBar().setIncrement(
652                     VERT_SCROLL_INCREMENT);
653         } else {
654             GC gc = new GC(sampleStyledText);
655             int width = gc.getFontMetrics().getAverageCharWidth();
656             gc.dispose();
657             this.scrolledComposite.getHorizontalBar().setIncrement(width);
658             this.scrolledComposite.getVerticalBar().setIncrement(
659                     sampleStyledText.getLineHeight());
660         }
661         return infoArea;
662     }
663
664     /**
665      * Creates the SWT controls for this workbench part.
666      * <p>
667      * Clients should not call this method (the workbench calls this method at
668      * appropriate times).
669      * </p>
670      * <p>
671      * For implementors this is a multi-step process:
672      * <ol>
673      * <li>Create one or more controls within the parent.</li>
674      * <li>Set the parent layout as needed.</li>
675      * <li>Register any global actions with the <code>IActionService</code>.</li>
676      * <li>Register any popup menus with the <code>IActionService</code>.</li>
677      * <li>Register a selection provider with the <code>ISelectionService</code>
678      * (optional). </li>
679      * </ol>
680      * </p>
681      *
682      * @param parent the parent control
683      */

684     public void createPartControl(Composite parent) {
685         // read our contents
686
readFile();
687         if (parser == null) {
688             return;
689         }
690
691         handCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
692         busyCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT);
693
694         editorComposite = new Composite(parent, SWT.NONE);
695         GridLayout layout = new GridLayout();
696         layout.marginHeight = 0;
697         layout.marginWidth = 0;
698         layout.verticalSpacing = 0;
699         layout.horizontalSpacing = 0;
700         editorComposite.setLayout(layout);
701
702         createTitleArea(editorComposite);
703
704         Label titleBarSeparator = new Label(editorComposite, SWT.HORIZONTAL
705                 | SWT.SEPARATOR);
706         GridData gd = new GridData(GridData.FILL_HORIZONTAL);
707         titleBarSeparator.setLayoutData(gd);
708
709         createInfoArea(editorComposite);
710
711         getSite().getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp(
712                 editorComposite, IIDEHelpContextIds.WELCOME_EDITOR);
713
714         this.colorListener = new IPropertyChangeListener() {
715             public void propertyChange(PropertyChangeEvent event) {
716                 if (event.getProperty()
717                         .equals(JFacePreferences.HYPERLINK_COLOR)) {
718                     Color fg = JFaceColors.getHyperlinkText(editorComposite
719                             .getDisplay());
720                     Iterator JavaDoc links = hyperlinkRanges.iterator();
721                     while (links.hasNext()) {
722                         StyleRange range = (StyleRange) links.next();
723                         range.foreground = fg;
724                     }
725                 }
726             }
727         };
728
729         JFacePreferences.getPreferenceStore().addPropertyChangeListener(
730                 this.colorListener);
731
732     }
733
734     /**
735      * Creates the wizard's title area.
736      *
737      * @param parent the SWT parent for the title area composite
738      * @return the created title area composite
739      */

740     private Composite createTitleArea(Composite parent) {
741         // Get the background color for the title area
742
Display display = parent.getDisplay();
743         Color background = JFaceColors.getBannerBackground(display);
744         Color foreground = JFaceColors.getBannerForeground(display);
745
746         // Create the title area which will contain
747
// a title, message, and image.
748
Composite titleArea = new Composite(parent, SWT.NONE | SWT.NO_FOCUS);
749         GridLayout layout = new GridLayout();
750         layout.marginHeight = 0;
751         layout.marginWidth = 0;
752         layout.verticalSpacing = 0;
753         layout.horizontalSpacing = 0;
754         layout.numColumns = 2;
755         titleArea.setLayout(layout);
756         titleArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
757         titleArea.setBackground(background);
758
759         // Message label
760
final CLabel messageLabel = new CLabel(titleArea, SWT.LEFT) {
761             protected String JavaDoc shortenText(GC gc, String JavaDoc text, int width) {
762                 if (gc.textExtent(text, SWT.DRAW_MNEMONIC).x <= width) {
763                     return text;
764                 }
765                 final String JavaDoc ellipsis = "..."; //$NON-NLS-1$
766
int ellipseWidth = gc.textExtent(ellipsis, SWT.DRAW_MNEMONIC).x;
767                 int length = text.length();
768                 int end = length - 1;
769                 while (end > 0) {
770                     text = text.substring(0, end);
771                     int l1 = gc.textExtent(text, SWT.DRAW_MNEMONIC).x;
772                     if (l1 + ellipseWidth <= width) {
773                         return text + ellipsis;
774                     }
775                     end--;
776                 }
777                 return text + ellipsis;
778             }
779         };
780         JFaceColors.setColors(messageLabel, foreground, background);
781         messageLabel.setText(getBannerTitle());
782         messageLabel.setFont(JFaceResources.getHeaderFont());
783
784         final IPropertyChangeListener fontListener = new IPropertyChangeListener() {
785             public void propertyChange(PropertyChangeEvent event) {
786                 if (JFaceResources.HEADER_FONT.equals(event.getProperty())) {
787                     messageLabel.setFont(JFaceResources.getHeaderFont());
788                 }
789             }
790         };
791
792         messageLabel.addDisposeListener(new DisposeListener() {
793             public void widgetDisposed(DisposeEvent event) {
794                 JFaceResources.getFontRegistry().removeListener(fontListener);
795             }
796         });
797
798         JFaceResources.getFontRegistry().addListener(fontListener);
799
800         GridData gd = new GridData(GridData.FILL_BOTH);
801         messageLabel.setLayoutData(gd);
802
803         // Title image
804
Label titleImage = new Label(titleArea, SWT.LEFT);
805         titleImage.setBackground(background);
806         titleImage.setImage(PlatformUI.getWorkbench().getSharedImages()
807                 .getImage(IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER));
808         gd = new GridData();
809         gd.horizontalAlignment = GridData.END;
810         titleImage.setLayoutData(gd);
811
812         return titleArea;
813     }
814
815     /**
816      * The <code>WorkbenchPart</code> implementation of this
817      * <code>IWorkbenchPart</code> method disposes the title image
818      * loaded by <code>setInitializationData</code>. Subclasses may extend.
819      */

820     public void dispose() {
821         super.dispose();
822         if (busyCursor != null) {
823             busyCursor.dispose();
824         }
825         if (handCursor != null) {
826             handCursor.dispose();
827         }
828         if (this.colorListener != null) {
829             JFacePreferences.getPreferenceStore().removePropertyChangeListener(
830                     this.colorListener);
831         }
832     }
833
834     /* (non-Javadoc)
835      * Saves the contents of this editor.
836      * <p>
837      * Subclasses must override this method to implement the open-save-close lifecycle
838      * for an editor. For greater details, see <code>IEditorPart</code>
839      * </p>
840      *
841      * @see IEditorPart
842      */

843     public void doSave(IProgressMonitor monitor) {
844         // do nothing
845
}
846
847     /* (non-Javadoc)
848      * Saves the contents of this editor to another object.
849      * <p>
850      * Subclasses must override this method to implement the open-save-close lifecycle
851      * for an editor. For greater details, see <code>IEditorPart</code>
852      * </p>
853      *
854      * @see IEditorPart
855      */

856     public void doSaveAs() {
857         // do nothing
858
}
859
860     /**
861      * Returns the title obtained from the parser
862      */

863     private String JavaDoc getBannerTitle() {
864         if (parser.getTitle() == null) {
865             return ""; //$NON-NLS-1$
866
}
867         return parser.getTitle();
868     }
869
870     /**
871      * Returns the intro item or <code>null</code>
872      */

873     private WelcomeItem getIntroItem() {
874         return parser.getIntroItem();
875     }
876
877     /**
878      * Returns the welcome items
879      */

880     private WelcomeItem[] getItems() {
881         return parser.getItems();
882     }
883
884     /* (non-Javadoc)
885      * Sets the cursor and selection state for this editor to the passage defined
886      * by the given marker.
887      * <p>
888      * Subclasses may override. For greater details, see <code>IEditorPart</code>
889      * </p>
890      *
891      * @see IEditorPart
892      */

893     public void gotoMarker(IMarker marker) {
894         // do nothing
895
}
896
897     /* (non-Javadoc)
898      * Initializes the editor part with a site and input.
899      * <p>
900      * Subclasses of <code>EditorPart</code> must implement this method. Within
901      * the implementation subclasses should verify that the input type is acceptable
902      * and then save the site and input. Here is sample code:
903      * </p>
904      * <pre>
905      * if (!(input instanceof IFileEditorInput))
906      * throw new PartInitException("Invalid Input: Must be IFileEditorInput");
907      * setSite(site);
908      * setInput(editorInput);
909      * </pre>
910      */

911     public void init(IEditorSite site, IEditorInput input)
912             throws PartInitException {
913         if (!(input instanceof WelcomeEditorInput)) {
914             throw new PartInitException(
915                     "Invalid Input: Must be WelcomeEditorInput"); //$NON-NLS-1$
916
}
917         setSite(site);
918         setInput(input);
919     }
920
921     /* (non-Javadoc)
922      * Returns whether the contents of this editor have changed since the last save
923      * operation.
924      * <p>
925      * Subclasses must override this method to implement the open-save-close lifecycle
926      * for an editor. For greater details, see <code>IEditorPart</code>
927      * </p>
928      *
929      * @see IEditorPart
930      */

931     public boolean isDirty() {
932         return false;
933     }
934
935     /* (non-Javadoc)
936      * Returns whether the "save as" operation is supported by this editor.
937      * <p>
938      * Subclasses must override this method to implement the open-save-close lifecycle
939      * for an editor. For greater details, see <code>IEditorPart</code>
940      * </p>
941      *
942      * @see IEditorPart
943      */

944     public boolean isSaveAsAllowed() {
945         return false;
946     }
947
948     /**
949      * Read the contents of the welcome page
950      *
951      * @param is the <code>InputStream</code> to parse
952      * @throws IOException if there is a problem parsing the stream.
953      */

954     public void read(InputStream JavaDoc is) throws IOException JavaDoc {
955         try {
956             parser = new WelcomeParser();
957         } catch (ParserConfigurationException JavaDoc e) {
958             throw (IOException JavaDoc) (new IOException JavaDoc().initCause(e));
959         } catch (SAXException JavaDoc e) {
960             throw (IOException JavaDoc) (new IOException JavaDoc().initCause(e));
961         }
962         parser.parse(is);
963     }
964
965     /**
966      * Reads the welcome file
967      */

968     public void readFile() {
969         URL JavaDoc url = ((WelcomeEditorInput) getEditorInput()).getAboutInfo()
970                 .getWelcomePageURL();
971
972         if (url == null) {
973             // should not happen
974
return;
975         }
976
977         InputStream JavaDoc is = null;
978         try {
979             is = url.openStream();
980             read(is);
981         } catch (IOException JavaDoc e) {
982             IStatus status = new Status(IStatus.ERROR,
983                     IDEWorkbenchPlugin.IDE_WORKBENCH, 1, IDEWorkbenchMessages.WelcomeEditor_accessException, e);
984             IDEWorkbenchPlugin.log(IDEWorkbenchMessages.WelcomeEditor_readFileError, status);
985         } finally {
986             try {
987                 if (is != null) {
988                     is.close();
989                 }
990             } catch (IOException JavaDoc e) {
991             }
992         }
993     }
994
995     /**
996      * Sets the styled text's bold ranges
997      */

998     private void setBoldRanges(StyledText styledText, int[][] boldRanges) {
999         for (int i = 0; i < boldRanges.length; i++) {
1000            StyleRange r = new StyleRange(boldRanges[i][0], boldRanges[i][1],
1001                    null, null, SWT.BOLD);
1002            styledText.setStyleRange(r);
1003        }
1004    }
1005
1006    /**
1007     * Asks this part to take focus within the workbench.
1008     * <p>
1009     * Clients should not call this method (the workbench calls this method at
1010     * appropriate times).
1011     * </p>
1012     */

1013    public void setFocus() {
1014        if ((editorComposite != null) && (lastNavigatedText == null)
1015                && (currentText == null)) {
1016            editorComposite.setFocus();
1017        }
1018    }
1019
1020    /**
1021     * Sets the styled text's link (blue) ranges
1022     */

1023    private void setLinkRanges(StyledText styledText, int[][] linkRanges) {
1024        //Color fg = styledText.getDisplay().getSystemColor(SWT.COLOR_BLUE);
1025
Color fg = JFaceColors.getHyperlinkText(styledText.getShell()
1026                .getDisplay());
1027        for (int i = 0; i < linkRanges.length; i++) {
1028            StyleRange r = new StyleRange(linkRanges[i][0], linkRanges[i][1],
1029                    fg, null);
1030            styledText.setStyleRange(r);
1031            hyperlinkRanges.add(r);
1032        }
1033    }
1034
1035}
1036
Popular Tags