001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.progress;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.jface.dialogs.IDialogConstants;
016: import org.eclipse.jface.resource.JFaceResources;
017: import org.eclipse.jface.viewers.ViewerComparator;
018: import org.eclipse.swt.SWT;
019: import org.eclipse.swt.custom.ScrolledComposite;
020: import org.eclipse.swt.events.ControlEvent;
021: import org.eclipse.swt.events.ControlListener;
022: import org.eclipse.swt.events.FocusAdapter;
023: import org.eclipse.swt.events.FocusEvent;
024: import org.eclipse.swt.graphics.Point;
025: import org.eclipse.swt.layout.GridData;
026: import org.eclipse.swt.layout.GridLayout;
027: import org.eclipse.swt.widgets.Composite;
028: import org.eclipse.swt.widgets.Control;
029: import org.eclipse.swt.widgets.Text;
030: import org.eclipse.swt.widgets.Widget;
031: import org.eclipse.ui.PlatformUI;
032: import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
033:
034: /**
035: * The DetailedProgressViewer is a viewer that shows the details of all in
036: * progress job or jobs that are finished awaiting user input.
037: *
038: * @since 3.2
039: *
040: */
041: public class DetailedProgressViewer extends AbstractProgressViewer {
042:
043: Composite control;
044:
045: private ScrolledComposite scrolled;
046:
047: private Composite noEntryArea;
048:
049: /**
050: * Create a new instance of the receiver with a control that is a child of
051: * parent with style style.
052: *
053: * @param parent
054: * @param style
055: */
056: public DetailedProgressViewer(Composite parent, int style) {
057: scrolled = new ScrolledComposite(parent, SWT.V_SCROLL | style);
058: int height = JFaceResources.getDefaultFont().getFontData()[0]
059: .getHeight();
060: scrolled.getVerticalBar().setIncrement(height * 2);
061: scrolled.setExpandHorizontal(true);
062: scrolled.setExpandVertical(true);
063:
064: control = new Composite(scrolled, SWT.NONE);
065: GridLayout layout = new GridLayout();
066: layout.marginHeight = 0;
067: layout.marginWidth = 0;
068: control.setLayout(layout);
069: control.setBackground(parent.getDisplay().getSystemColor(
070: SWT.COLOR_LIST_BACKGROUND));
071:
072: control.addFocusListener(new FocusAdapter() {
073:
074: private boolean settingFocus = false;
075:
076: /*
077: * (non-Javadoc)
078: *
079: * @see org.eclipse.swt.events.FocusAdapter#focusGained(org.eclipse.swt.events.FocusEvent)
080: */
081: public void focusGained(FocusEvent e) {
082: if (!settingFocus) {
083: //Prevent new focus events as a result this update occurring
084: settingFocus = true;
085: setFocus();
086: settingFocus = false;
087: }
088: }
089: });
090:
091: control.addControlListener(new ControlListener() {
092: /*
093: * (non-Javadoc)
094: *
095: * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
096: */
097: public void controlMoved(ControlEvent e) {
098: updateVisibleItems();
099:
100: }
101:
102: /*
103: * (non-Javadoc)
104: *
105: * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
106: */
107: public void controlResized(ControlEvent e) {
108: updateVisibleItems();
109: }
110: });
111:
112: PlatformUI.getWorkbench().getHelpSystem().setHelp(control,
113: IWorkbenchHelpContextIds.RESPONSIVE_UI);
114:
115: scrolled.setContent(control);
116: hookControl(control);
117:
118: noEntryArea = new Composite(scrolled, SWT.NONE);
119: noEntryArea.setLayout(new GridLayout());
120:
121: Text noEntryLabel = new Text(noEntryArea, SWT.SINGLE);
122: noEntryLabel
123: .setText(ProgressMessages.ProgressView_NoOperations);
124: noEntryLabel.setBackground(noEntryArea.getDisplay()
125: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
126: GridData textData = new GridData(
127: GridData.VERTICAL_ALIGN_BEGINNING);
128: noEntryLabel.setLayoutData(textData);
129: noEntryLabel.setEditable(false);
130:
131: PlatformUI.getWorkbench().getHelpSystem().setHelp(noEntryLabel,
132: IWorkbenchHelpContextIds.RESPONSIVE_UI);
133:
134: }
135:
136: /*
137: * (non-Javadoc)
138: *
139: * @see org.eclipse.ui.internal.progress.AbstractProgressViewer#add(java.lang.Object[])
140: */
141: public void add(Object[] elements) {
142: ViewerComparator sorter = getComparator();
143: ArrayList newItems = new ArrayList(control.getChildren().length
144: + elements.length);
145:
146: Control[] existingChildren = control.getChildren();
147: for (int i = 0; i < existingChildren.length; i++) {
148: newItems.add(existingChildren[i].getData());
149: }
150:
151: for (int i = 0; i < elements.length; i++) {
152: newItems.add(elements[i]);
153: }
154:
155: JobTreeElement[] infos = new JobTreeElement[newItems.size()];
156: newItems.toArray(infos);
157:
158: if (sorter != null) {
159: sorter.sort(this , infos);
160: }
161:
162: // Update with the new elements to prevent flash
163: for (int i = 0; i < existingChildren.length; i++) {
164: ((ProgressInfoItem) existingChildren[i]).dispose();
165: }
166:
167: for (int i = 0; i < newItems.size(); i++) {
168: ProgressInfoItem item = createNewItem(infos[i]);
169: item.setColor(i);
170: }
171:
172: control.layout(true);
173: updateForShowingProgress();
174: }
175:
176: /**
177: * Update for the progress being displayed.
178: */
179: private void updateForShowingProgress() {
180: if (control.getChildren().length > 0) {
181: scrolled.setContent(control);
182: } else {
183: scrolled.setContent(noEntryArea);
184: }
185: }
186:
187: /**
188: * Create a new item for info.
189: *
190: * @param info
191: * @return ProgressInfoItem
192: */
193: private ProgressInfoItem createNewItem(JobTreeElement info) {
194: final ProgressInfoItem item = new ProgressInfoItem(control,
195: SWT.NONE, info);
196:
197: item.setIndexListener(new ProgressInfoItem.IndexListener() {
198: /*
199: * (non-Javadoc)
200: *
201: * @see org.eclipse.ui.internal.progress.ProgressInfoItem.IndexListener#selectNext()
202: */
203: public void selectNext() {
204: DetailedProgressViewer.this .selectNext(item);
205:
206: }
207:
208: /*
209: * (non-Javadoc)
210: *
211: * @see org.eclipse.ui.internal.progress.ProgressInfoItem.IndexListener#selectPrevious()
212: */
213: public void selectPrevious() {
214: DetailedProgressViewer.this .selectPrevious(item);
215:
216: }
217:
218: /*
219: * (non-Javadoc)
220: *
221: * @see org.eclipse.ui.internal.progress.ProgressInfoItem.IndexListener#select()
222: */
223: public void select() {
224:
225: Control[] children = control.getChildren();
226: for (int i = 0; i < children.length; i++) {
227: ProgressInfoItem child = (ProgressInfoItem) children[i];
228: if (!item.equals(child)) {
229: child.selectWidgets(false);
230: }
231: }
232: item.selectWidgets(true);
233:
234: }
235: });
236:
237: // Refresh to populate with the current tasks
238: item.refresh();
239: return item;
240: }
241:
242: /**
243: * Select the previous item in the receiver.
244: *
245: * @param item
246: */
247: protected void selectPrevious(ProgressInfoItem item) {
248: Control[] children = control.getChildren();
249: for (int i = 0; i < children.length; i++) {
250: ProgressInfoItem child = (ProgressInfoItem) children[i];
251: if (item.equals(child)) {
252: ProgressInfoItem previous;
253: if (i == 0) {
254: previous = (ProgressInfoItem) children[children.length - 1];
255: } else {
256: previous = (ProgressInfoItem) children[i - 1];
257: }
258:
259: item.selectWidgets(false);
260: previous.selectWidgets(true);
261: return;
262: }
263: }
264: }
265:
266: /**
267: * Select the next item in the receiver.
268: *
269: * @param item
270: */
271: protected void selectNext(ProgressInfoItem item) {
272: Control[] children = control.getChildren();
273: for (int i = 0; i < children.length; i++) {
274: ProgressInfoItem child = (ProgressInfoItem) children[i];
275: if (item.equals(child)) {
276: ProgressInfoItem next;
277: if (i == children.length - 1) {
278: next = (ProgressInfoItem) children[0];
279: } else {
280: next = (ProgressInfoItem) children[i + 1];
281: }
282: item.selectWidgets(false);
283: next.selectWidgets(true);
284:
285: return;
286: }
287: }
288:
289: }
290:
291: /*
292: * (non-Javadoc)
293: *
294: * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
295: */
296: protected Widget doFindInputItem(Object element) {
297: return null;
298: }
299:
300: /*
301: * (non-Javadoc)
302: *
303: * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
304: */
305: protected Widget doFindItem(Object element) {
306: Control[] existingChildren = control.getChildren();
307: for (int i = 0; i < existingChildren.length; i++) {
308: if (existingChildren[i].isDisposed()
309: || existingChildren[i].getData() == null) {
310: continue;
311: }
312: if (existingChildren[i].getData().equals(element)) {
313: return existingChildren[i];
314: }
315: }
316: return null;
317: }
318:
319: /*
320: * (non-Javadoc)
321: *
322: * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget,
323: * java.lang.Object, boolean)
324: */
325: protected void doUpdateItem(Widget item, Object element,
326: boolean fullMap) {
327: if (usingElementMap()) {
328: unmapElement(item);
329: }
330: item.dispose();
331: add(new Object[] { element });
332: }
333:
334: /*
335: * (non-Javadoc)
336: *
337: * @see org.eclipse.jface.viewers.Viewer#getControl()
338: */
339: public Control getControl() {
340: return scrolled;
341: }
342:
343: /*
344: * (non-Javadoc)
345: *
346: * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
347: */
348: protected List getSelectionFromWidget() {
349: return new ArrayList(0);
350: }
351:
352: /*
353: * (non-Javadoc)
354: *
355: * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
356: * java.lang.Object)
357: */
358: protected void inputChanged(Object input, Object oldInput) {
359: super .inputChanged(input, oldInput);
360: refreshAll();
361: updateForShowingProgress();
362: }
363:
364: /*
365: * (non-Javadoc)
366: *
367: * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
368: */
369: protected void internalRefresh(Object element) {
370: if (element == null) {
371: return;
372: }
373:
374: if (element.equals(getRoot())) {
375: refreshAll();
376: return;
377: }
378: Widget widget = findItem(element);
379: if (widget == null) {
380: add(new Object[] { element });
381: return;
382: }
383: ((ProgressInfoItem) widget).refresh();
384:
385: // Update the minimum size
386: Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT);
387: size.x += IDialogConstants.HORIZONTAL_SPACING;
388: size.y += IDialogConstants.VERTICAL_SPACING;
389:
390: scrolled.setMinSize(size);
391: }
392:
393: /*
394: * (non-Javadoc)
395: *
396: * @see org.eclipse.ui.internal.progress.AbstractProgressViewer#remove(java.lang.Object[])
397: */
398: public void remove(Object[] elements) {
399:
400: for (int i = 0; i < elements.length; i++) {
401:
402: // Make sure we are not keeping this one
403: if (((JobTreeElement) elements[i]).isJobInfo()
404: && FinishedJobs.getInstance().isFinished(
405: (JobInfo) elements[i])) {
406: Widget item = doFindItem(elements[i]);
407: if (item != null) {
408: ((ProgressInfoItem) item).refresh();
409: }
410:
411: } else {
412: Widget item = doFindItem(elements[i]);
413: if (item != null) {
414: unmapElement(elements[i]);
415: item.dispose();
416: }
417: }
418: }
419:
420: Control[] existingChildren = control.getChildren();
421: for (int i = 0; i < existingChildren.length; i++) {
422: ProgressInfoItem item = (ProgressInfoItem) existingChildren[i];
423: item.setColor(i);
424: }
425: control.layout(true);
426: updateForShowingProgress();
427: }
428:
429: /*
430: * (non-Javadoc)
431: *
432: * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
433: */
434: public void reveal(Object element) {
435:
436: }
437:
438: /*
439: * (non-Javadoc)
440: *
441: * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
442: * boolean)
443: */
444: protected void setSelectionToWidget(List l, boolean reveal) {
445:
446: }
447:
448: /**
449: * Cancel the current selection
450: *
451: */
452: public void cancelSelection() {
453:
454: }
455:
456: /**
457: * Set focus on the current selection.
458: *
459: */
460: public void setFocus() {
461: Control[] children = control.getChildren();
462: if (children.length > 0) {
463: for (int i = 0; i < children.length; i++) {
464: ProgressInfoItem item = (ProgressInfoItem) children[i];
465: item.setButtonFocus();
466: return;
467: }
468: } else
469: noEntryArea.setFocus();
470: }
471:
472: /**
473: * Refresh everything as the root is being refreshed.
474: */
475: private void refreshAll() {
476:
477: Object[] infos = getSortedChildren(getRoot());
478: Control[] existingChildren = control.getChildren();
479:
480: for (int i = 0; i < existingChildren.length; i++) {
481: existingChildren[i].dispose();
482:
483: }
484: // Create new ones if required
485: for (int i = 0; i < infos.length; i++) {
486: ProgressInfoItem item = createNewItem((JobTreeElement) infos[i]);
487: item.setColor(i);
488: }
489:
490: control.layout(true);
491: updateForShowingProgress();
492:
493: }
494:
495: /**
496: * Set the virtual items to be visible or not depending on the displayed
497: * area.
498: */
499: private void updateVisibleItems() {
500: Control[] children = control.getChildren();
501: int top = scrolled.getOrigin().y;
502: int bottom = top + scrolled.getParent().getBounds().height;
503: for (int i = 0; i < children.length; i++) {
504: ProgressInfoItem item = (ProgressInfoItem) children[i];
505: item.setDisplayed(top, bottom);
506:
507: }
508: }
509:
510: }
|