/* ImageButton.java (c) 2009-2013 Edward Swartz 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 */ package v9t9.gui.client.swt.bars; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.events.MouseTrackListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import v9t9.gui.client.swt.IFocusRestorer; /** * A button with an image, which is allowed to be transparent. * @author ejs * */ public class ImageButton extends ImageIconCanvas { private List<SelectionListener> listeners; private boolean selected; private boolean isHighlighted; private boolean pressed; // private boolean isMenuHovering; // private Rectangle menuOverlayBounds; protected IFocusRestorer focusRestorer; private List<Rectangle> imageOverlays = new LinkedList<Rectangle>(); private String baseTooltip; private List<IImageButtonAreaHandler> areaHandlers = new ArrayList<IImageButtonAreaHandler>(); private List<IImageButtonAreaHandler> mouseDownActiveHandlers = new ArrayList<IImageButtonAreaHandler>(); private IImageButtonAreaHandler lastMousedAreaHandler = null; public ImageButton(IImageCanvas parentBar, int style, IImageProvider imageProvider, int iconIndex, String tooltip) { super(parentBar, style, imageProvider, iconIndex, tooltip); baseTooltip = tooltip; this.listeners = new ArrayList<SelectionListener>(); addListener(SWT.MouseDown, new Listener() { @Override public void handleEvent(Event e) { if (parentDrawer.isRetracted()) { e.doit = false; return; } boolean wasHandled = false; for (IImageButtonAreaHandler handler : areaHandlers) { if (handler.isInBounds(e.x, e.y, getSize()) && handler.isActive()) { if (e.button == 1 && handler.isMenu()) { Event me = new Event(); me.button = e.button; me.display = e.display; me.item = ImageButton.this; me.stateMask = e.stateMask; me.type = SWT.MenuDetect; me.widget = ImageButton.this; me.x = e.x; me.y = e.y; notifyListeners(SWT.MenuDetect, me); e.doit = false; return; } wasHandled = handler.mouseDown(e.button); if (wasHandled) { if (!mouseDownActiveHandlers.contains(handler)) mouseDownActiveHandlers.add(handler); e.doit = false; break; } } } if (!wasHandled && e.button == 1) { doClickStart(); } } }); addListener(SWT.MouseUp, new Listener() { @Override public void handleEvent(Event e) { if (parentDrawer.isRetracted()) { e.doit = false; return; } boolean wasHandled = false; for (IImageButtonAreaHandler handler : areaHandlers) { if (handler.isInBounds(e.x, e.y, getSize()) && mouseDownActiveHandlers.contains(handler)) { mouseDownActiveHandlers.remove(handler); wasHandled = handler.mouseUp(e.button); if (wasHandled) { e.doit = false; break; } } } if (!wasHandled && e.button == 1) { doClickStop(e); } if (focusRestorer != null) focusRestorer.restoreFocus(); } }); addMouseTrackListener(new MouseTrackListener() { public void mouseEnter(MouseEvent e) { if (parentDrawer.isRetracted()) return; doMouseEnter(e); } public void mouseExit(MouseEvent e) { if (parentDrawer.isRetracted()) return; doMouseExit(e); } public void mouseHover(MouseEvent e) { if (parentDrawer.isRetracted()) return; doMouseHover(e); } }); addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent e) { if (parentDrawer.isRetracted()) return; doMouseMove(e); } }); //setRetracted(false); setCursor(getDisplay().getSystemCursor(SWT.CURSOR_HAND)); addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { for (IImageButtonAreaHandler handler : areaHandlers) { handler.detach(ImageButton.this); } areaHandlers.clear(); } }); } /** * @return the imageOverlays */ public List<Rectangle> getImageOverlays() { return imageOverlays; } public void setOverlayBounds(Rectangle overlayBounds) { imageOverlays.clear(); if (overlayBounds != null) imageOverlays.add(overlayBounds); } public void addImageOverlay(Rectangle overlayBounds) { if (overlayBounds == null || overlayBounds.isEmpty()) return; if (!imageOverlays.contains(overlayBounds)) { imageOverlays.add(overlayBounds); redraw(); } } public void removeImageOverlay(Rectangle overlayBounds) { if (overlayBounds == null || overlayBounds.isEmpty()) return; imageOverlays.remove(overlayBounds); redraw(); } public void clearImageOverlays() { imageOverlays.clear(); } public void setFocusRestorer(IFocusRestorer focusRestorer) { this.focusRestorer = focusRestorer; } public void addSelectionListener(SelectionListener listener) { listeners.add(listener); } public boolean getSelection() { if ((getStyle() & SWT.PUSH) != 0) return selected; else return pressed; } public void setSelection(boolean flag) { if (flag != selected) { this.selected = flag; redraw(); } } protected void updateDrawRect(Rectangle drawRect) { int offset = 0; if ((getStyle() & SWT.TOGGLE) != 0) { if (pressed && imageOverlays.isEmpty()) { offset = 2; } } else { } offset = pressed ? 2 : 0; drawRect.x += offset; drawRect.y += offset; } /** * @param e */ @Override protected void drawImage(PaintEvent e) { Rectangle drawRect = getBounds(); Point po = parentDrawer.getPaintOffset(); //e.gc.setAntialias(SWT.ON); drawRect.x = po.x; drawRect.y = po.y; if ((getStyle() & SWT.TOGGLE) != 0) { if (pressed && imageOverlays.isEmpty()) { Color bg = e.gc.getBackground(); e.gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); e.gc.fillRectangle(po.x, po.y, drawRect.width, drawRect.height); e.gc.setBackground(bg); } } updateDrawRect(drawRect); try { if (bounds.width > 0) { imageProvider.drawImage(e.gc, 255 - invAlpha, drawRect, bounds); } drawRect.x = po.x; drawRect.y = po.y; for (Rectangle imgRect : imageOverlays) { imageProvider.drawImage(e.gc, 255 - invAlpha, drawRect, imgRect); } // if (menuOverlayBounds != null && isMenuHovering) { // imageProvider.drawImage(e.gc, drawRect, menuOverlayBounds); // } } catch (IllegalArgumentException e2) { e2.printStackTrace(); } //e.gc.setAntialias(SWT.OFF); if (isHighlighted) { e.gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK)); //e.gc.setLineStyle(SWT.LINE_DOT); //e.gc.drawRectangle(0, 0, imgRect.width - 1, imgRect.height - 1); e.gc.drawFocus(po.x, po.y, drawRect.width - 1, drawRect.height - 1); } } protected void doClickStart() { if ((getStyle() & SWT.PUSH) != 0) pressed = true; redraw(); } protected void doClickStop(Event e) { if ((getStyle() & SWT.PUSH) != 0) pressed = false; else if ((getStyle() & SWT.TOGGLE) != 0) pressed = !pressed; redraw(); // released outside button Point size = getSize(); if (e.x < 0 || e.y < 0 || e.x > size.x || e.y > size.y) return; SelectionListener[] array = (SelectionListener[]) listeners.toArray(new SelectionListener[listeners.size()]); Event event = new Event(); event.widget = this; event.x = e.x; event.y = e.y; SelectionEvent selEvent = new SelectionEvent(event); for (SelectionListener listener : array) { listener.widgetSelected(selEvent); } } protected void doMouseEnter(MouseEvent e) { if (parentDrawer.isRetracted()) return; isHighlighted = true; setToolTipText(baseTooltip); for (IImageButtonAreaHandler handler : areaHandlers) { if (handler.isInBounds(e.x, e.y, getSize()) && handler.isActive()) { handler.mouseEnter(); String tt = handler.getTooltip(); if (tt != null) { setToolTipText(tt); } setMousedArea(handler); return; } } resetMousedArea(); } /** * @param handler */ private void setMousedArea(IImageButtonAreaHandler handler) { if (handler != lastMousedAreaHandler) { if (lastMousedAreaHandler != null) { lastMousedAreaHandler.mouseExit(); } lastMousedAreaHandler = handler; handler.mouseEnter(); String tt = handler.getTooltip(); if (tt != null) setToolTipText(tt); redraw(); } } protected void doMouseHover(MouseEvent e) { for (IImageButtonAreaHandler handler : areaHandlers) { if (handler.isInBounds(e.x, e.y, getSize()) && handler.isActive()) { setMousedArea(handler); handler.mouseHover(); return; } } resetMousedArea(); } protected void doMouseMove(MouseEvent e) { for (IImageButtonAreaHandler handler : areaHandlers) { if (handler.isInBounds(e.x, e.y, getSize()) && handler.isActive()) { setMousedArea(handler); return; } } resetMousedArea(); } /** * */ private void resetMousedArea() { if (lastMousedAreaHandler != null) lastMousedAreaHandler.mouseExit(); lastMousedAreaHandler = null; setToolTipText(baseTooltip); redraw(); } /** * @param e */ protected void doMouseExit(MouseEvent e) { if (parentDrawer.isRetracted()) return; isHighlighted = false; redraw(); for (IImageButtonAreaHandler handler : areaHandlers) { if (handler.isInBounds(e.x, e.y, getSize()) && handler.isActive()) { handler.mouseExit(); String tt = handler.getTooltip(); if (tt != null) setToolTipText(baseTooltip); break; } } resetMousedArea(); } public void addAreaHandler(IImageButtonAreaHandler handler) { if (!areaHandlers.contains(handler)) { areaHandlers.add(handler); handler.attach(this); } } // private void checkMenu(MouseEvent e) { // for (IImageButtonAreaHandler handler : areaHandlers) { // if (handler.getBounds(getSize()).contains(e.x, e.y) && handler.isActive()) { // handler.mouseEnter(); // } else { // handler.mouseExit(); // } // } // } // // if (menuOverlayBounds != null) { // boolean isOverMenu = isEventOverMenu(e); // // if (isOverMenu) { // if (!isMenuHovering) { // isMenuHovering = true; // redraw(); // } // return; // } // if (isMenuHovering) { // isMenuHovering = false; // redraw(); // } // } // // } /** * @param e * @return */ // protected boolean isEventOverMenu(MouseEvent e) { // boolean isOverMenu; // Point corner = getSize(); // corner.x -= corner.x / 3; // corner.y -= corner.y / 3; // isOverMenu = (e.x >= corner.x // && e.y >= corner.y); // return isOverMenu; // } }