/******************************************************************************* * Copyright 2011 Google Inc. All Rights Reserved. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.google.gwt.eclipse.oophm.breadcrumbs; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; /** * The label and icon part of the breadcrumb item. * * NOTE: This code was derived from * org.eclipse.jdt.internal.ui.javaeditor.breadcrumb.BreadcrumbItemDetails. * * @since 3.4 */ class BreadcrumbItemDetails { private final Label fElementImage; private final Label fElementText; private final Composite fDetailComposite; private final BreadcrumbItem fParent; private final Composite fTextComposite; private final Composite fImageComposite; private boolean fTextVisible; private boolean fSelected; private boolean fHasFocus; public BreadcrumbItemDetails(BreadcrumbItem parent, Composite parentContainer) { fParent = parent; fTextVisible = true; fDetailComposite = new Composite(parentContainer, SWT.NONE); fDetailComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); GridLayout layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; layout.horizontalSpacing = 0; fDetailComposite.setLayout(layout); addElementListener(fDetailComposite); fImageComposite = new Composite(fDetailComposite, SWT.NONE); fImageComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); layout = new GridLayout(1, false); layout.marginHeight = 1; layout.marginWidth = 2; fImageComposite.setLayout(layout); fImageComposite.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (fHasFocus && !isTextVisible()) { e.gc.drawFocus(e.x, e.y, e.width, e.height); } } }); installFocusComposite(fImageComposite); addElementListener(fImageComposite); fElementImage = new Label(fImageComposite, SWT.NONE); GridData layoutData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false); fElementImage.setLayoutData(layoutData); addElementListener(fElementImage); fTextComposite = new Composite(fDetailComposite, SWT.NONE); fTextComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); layout = new GridLayout(1, false); layout.marginHeight = 2; layout.marginWidth = 2; fTextComposite.setLayout(layout); addElementListener(fTextComposite); fTextComposite.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (fHasFocus && isTextVisible()) { e.gc.drawFocus(e.x, e.y, e.width, e.height); } } }); installFocusComposite(fTextComposite); addElementListener(fTextComposite); fElementText = new Label(fTextComposite, SWT.NONE); layoutData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false); fElementText.setLayoutData(layoutData); addElementListener(fElementText); fTextComposite.getAccessible().addAccessibleListener( new AccessibleAdapter() { public void getName(AccessibleEvent e) { e.result = fElementText.getText(); } }); fImageComposite.getAccessible().addAccessibleListener( new AccessibleAdapter() { public void getName(AccessibleEvent e) { e.result = fElementText.getText(); } }); fDetailComposite.setTabList(new Control[] {fTextComposite}); } /** * Returns the width of this element. * * @return current width of this element */ public int getWidth() { int result = 2; if (fElementImage.getImage() != null) result += fElementImage.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; if (fTextVisible && fElementText.getText().length() > 0) result += fElementText.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; return result; } /** * Returns whether this element has the keyboard focus. * * @return true if this element has the keyboard focus. */ public boolean hasFocus() { return fHasFocus; } /** * Tells whether this item shows a text or only an image. * * @return <code>true</code> if it shows a text and an image, false if it only * shows the image */ public boolean isTextVisible() { return fTextVisible; } public void setFocus(boolean enabled) { if (enabled == fHasFocus) return; fHasFocus = enabled; if (fHasFocus) { if (isTextVisible()) { fTextComposite.setFocus(); } else { fImageComposite.setFocus(); } } updateSelection(); } /** * Sets the image to the given image. * * @param image the image to use */ public void setImage(Image image) { if (image != fElementImage.getImage()) { fElementImage.setImage(image); } } public void setSelected(boolean selected) { if (selected == fSelected) return; fSelected = selected; if (!fSelected) fHasFocus = false; updateSelection(); } /** * Sets the text to the given text. * * @param text the text to use */ public void setText(String text) { if (text == null) { text = ""; //$NON-NLS-1$ } if (!text.equals(fElementText.getText())) { fElementText.setText(text); } } public void setTextVisible(boolean enabled) { if (fTextVisible == enabled) return; fTextVisible = enabled; GridData data = (GridData) fTextComposite.getLayoutData(); data.exclude = !enabled; fTextComposite.setVisible(enabled); if (fTextVisible) { fDetailComposite.setTabList(new Control[] {fTextComposite}); } else { fDetailComposite.setTabList(new Control[] {fImageComposite}); } if (fHasFocus) { if (isTextVisible()) { fTextComposite.setFocus(); } else { fImageComposite.setFocus(); } } updateSelection(); } /** * Sets the tool tip to the given text. * * @param text the tool tip */ public void setToolTip(String text) { if (isTextVisible()) { fElementText.getParent().setToolTipText(text); fElementText.setToolTipText(text); fElementImage.setToolTipText(text); } else { fElementText.getParent().setToolTipText(null); fElementText.setToolTipText(null); fElementImage.setToolTipText(text); } } /** * Sets whether details should be shown. * * @param visible <code>true</code> if details should be shown */ public void setVisible(boolean visible) { fDetailComposite.setVisible(visible); GridData data = (GridData) fDetailComposite.getLayoutData(); data.exclude = !visible; } /** * Add mouse listeners to the given control. * * @param control the control to which may be clicked */ private void addElementListener(Control control) { control.addMouseListener(new MouseListener() { public void mouseDoubleClick(MouseEvent e) { } public void mouseDown(MouseEvent e) { BreadcrumbViewer viewer = fParent.getViewer(); int parentIndex = viewer.getIndexOfItem(fParent) - 1; Shell shell = null; if (parentIndex >= 0) {// sanity check, must always hold BreadcrumbItem dropDownItem = viewer.getItem(parentIndex); shell = dropDownItem.getDropDownShell(); } viewer.selectItem(fParent); if (shell == null && e.button == 1 && e.stateMask == 0) { fParent.getViewer().fireDoubleClick(); } } public void mouseUp(MouseEvent e) { } }); control.addMenuDetectListener(new MenuDetectListener() { public void menuDetected(MenuDetectEvent e) { BreadcrumbViewer viewer = fParent.getViewer(); viewer.selectItem(fParent); fParent.getViewer().fireMenuDetect(e); } }); } /** * Install focus and key listeners to the given composite. * * @param composite the composite which may get focus */ private void installFocusComposite(Composite composite) { composite.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) { int index = fParent.getViewer().getIndexOfItem(fParent); if (e.detail == SWT.TRAVERSE_TAB_NEXT) { index++; } else { index--; } if (index > 0 && index < fParent.getViewer().getItemCount()) { fParent.getViewer().selectItem(fParent.getViewer().getItem(index)); } e.doit = true; } } }); composite.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { BreadcrumbViewer viewer = fParent.getViewer(); switch (e.keyCode) { case SWT.ARROW_LEFT: if (fSelected) { viewer.doTraverse(false); e.doit = false; } else { viewer.selectItem(fParent); } break; case SWT.ARROW_RIGHT: if (fSelected) { viewer.doTraverse(true); e.doit = false; } else { viewer.selectItem(fParent); } break; case SWT.ARROW_DOWN: if (!fSelected) { viewer.selectItem(fParent); } openDropDown(); e.doit = false; break; case SWT.KEYPAD_ADD: if (!fSelected) { viewer.selectItem(fParent); } openDropDown(); e.doit = false; break; case SWT.CR: if (!fSelected) { viewer.selectItem(fParent); } viewer.fireOpen(); break; default: if (e.character == ' ') { if (!fSelected) { viewer.selectItem(fParent); } openDropDown(); e.doit = false; } break; } } public void keyReleased(KeyEvent e) { } private void openDropDown() { BreadcrumbViewer viewer = fParent.getViewer(); int index = viewer.getIndexOfItem(fParent); BreadcrumbItem parent = fParent.getViewer().getItem(index - 1); Shell shell = parent.getDropDownShell(); if (shell == null) { parent.openDropDownMenu(); shell = parent.getDropDownShell(); } shell.setFocus(); } }); composite.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { if (!fHasFocus) { fHasFocus = true; updateSelection(); } } public void focusLost(FocusEvent e) { if (fHasFocus) { fHasFocus = false; updateSelection(); } } }); } private void updateSelection() { Color background; Color foreground; if (fSelected && fHasFocus) { background = Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION); foreground = Display.getDefault().getSystemColor( SWT.COLOR_LIST_SELECTION_TEXT); } else { foreground = null; background = null; } if (isTextVisible()) { fTextComposite.setBackground(background); fElementText.setBackground(background); fElementText.setForeground(foreground); fImageComposite.setBackground(null); fElementImage.setBackground(null); } else { fImageComposite.setBackground(background); fElementImage.setBackground(background); fTextComposite.setBackground(null); fElementText.setBackground(null); fElementText.setForeground(null); } fTextComposite.redraw(); fImageComposite.redraw(); } }