/*******************************************************************************
* Copyright (c) Emil Crumhorn - Hexapixel.com - emil.crumhorn@gmail.com
* 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
*
* Contributors:
* emil.crumhorn@gmail.com - initial API and implementation
*******************************************************************************/
package com.hexapixel.widgets.ribbon;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import com.hexapixel.widgets.generic.ColorCache;
public class RibbonGroup extends Canvas implements MouseMoveListener, MouseListener, MouseTrackListener {
private String mGroupName;
private int mBorderSize = 2;
// gradient marks
public static int BUTTON_TOP_HEIGHT = 13;
public static int BUTTON_MID_HEIGHT = 54;
public static int BUTTON_BOT_HEIGHT = 14;
public static int BUTTON_SPACING = 0;
public static int BUTTON_HEIGHT = 66;
public static int TOOLBAR_BUTTON_HEIGHT = 22;
public static int TOOLBAR_BUTTON_HEIGHT_BORDERED = 20;
public static int TOOLBAR_BUTTON_WIDTH = 22;
public static int TOOLBAR_BUTTON_WIDTH_BORDERED = 22;
public static int CHECKBOX_HEIGHT = 13;
private boolean mVisible = true;
// COLORS
private Color mBorderBlueTop = ColorCache.getInstance().getColor(197, 210, 223);
private Color mBorderBlueSideTopTop = ColorCache.getInstance().getColor(195, 209, 222);
private Color mBorderBlueSideTopBottom = ColorCache.getInstance().getColor(179, 198, 214);
private Color mBorderBlueSideBottomTop = ColorCache.getInstance().getColor(175, 195, 213);
private Color mBorderBlueSideBottomBottom = ColorCache.getInstance().getColor(157, 191, 219);
private Color mBorderBlueBottom = ColorCache.getInstance().getColor(158, 191, 219);
private Color mBorderFadePixelTop = ColorCache.getInstance().getColor(208, 220, 232);
private Color mBorderFadePixelBottom = ColorCache.getInstance().getColor(187, 213, 232);
private Color mBorderBlueTop_Hover = ColorCache.getInstance().getColor(173, 199, 222);
private Color mBorderBlueSideTopTop_Hover = ColorCache.getInstance().getColor(172, 199, 222);
private Color mBorderBlueSideTopBottom_Hover = ColorCache.getInstance().getColor(165, 196, 220);
private Color mBorderBlueSideBottomTop_Hover = ColorCache.getInstance().getColor(165, 196, 220);
private Color mBorderBlueSideBottomBottom_Hover = ColorCache.getInstance().getColor(127, 173, 211);
private Color mBorderBlueBottom_Hover = ColorCache.getInstance().getColor(126, 173, 211);
private Color mBorderFadePixelTop_Hover = ColorCache.getInstance().getColor(193, 212, 231);
private Color mBorderFadePixelBottom_Hover = ColorCache.getInstance().getColor(167, 201, 228);
private Color mBorderInnerFadePixelTop = ColorCache.getInstance().getColor(232, 239, 247);
private Color mBorderInnerBlueTop = ColorCache.getInstance().getColor(237, 242, 248);
private Color mBorderInnerSideTopTop = ColorCache.getInstance().getColor(236, 241, 248);
private Color mBorderInnerSideTopBottom = ColorCache.getInstance().getColor(230, 237, 246);
private Color mBorderInnerSideMidTop = ColorCache.getInstance().getColor(225, 234, 244);
private Color mBorderInnerSideMidBottom = ColorCache.getInstance().getColor(234, 242, 248);
private Color mBorderInnerSideBottomTop = ColorCache.getInstance().getColor(206, 224, 243);
private Color mBorderInnerSideBottomBottom = ColorCache.getInstance().getColor(201, 221, 240);
private Color mBorderInnerBlueTop_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mBorderInnerSideTopTop_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mBorderInnerSideTopBottom_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mBorderInnerSideMidTop_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mBorderInnerSideMidBottom_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mBorderInnerSideBottomTop_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mBorderInnerSideBottomBottom_Hover = ColorCache.getInstance().getColor(255, 255, 255);
private Color mShadowTopTop = ColorCache.getInstance().getColor(237, 242, 248);
private Color mShadowTopBottom = ColorCache.getInstance().getColor(230, 237, 246);
private Color mShadowMidTop = ColorCache.getInstance().getColor(225, 234, 244);
private Color mShadowMidBottom = ColorCache.getInstance().getColor(234, 242, 248);
private Color mShadowBottomTop = ColorCache.getInstance().getColor(234, 242, 249);
private Color mShadowBottomBottom = ColorCache.getInstance().getColor(239, 248, 253);
private Color mShadowFadePixel = ColorCache.getInstance().getColor(231, 238, 247);
private Color mInnerFillTopTop = ColorCache.getInstance().getColor(222, 232, 245);
private Color mInnerFillTopBottom = ColorCache.getInstance().getColor(209, 223, 240);
private Color mInnerFillMidTop = ColorCache.getInstance().getColor(199, 216, 237);
private Color mInnerFillMidBottm = ColorCache.getInstance().getColor(216, 232, 245);
private Color mInnerFillBottomTop = ColorCache.getInstance().getColor(194, 216, 241);
private Color mInnerFillBottomBottom = ColorCache.getInstance().getColor(192, 216, 239);
private Color mInnerFillTopTop_Hover = ColorCache.getInstance().getColor(228, 239, 253);
private Color mInnerFillTopBottom_Hover = ColorCache.getInstance().getColor(232, 240, 252);
private Color mInnerFillMidTop_Hover = ColorCache.getInstance().getColor(220, 234, 251);
private Color mInnerFillMidBottm_Hover = ColorCache.getInstance().getColor(220, 232, 248);
private Color mInnerFillBottomTop_Hover = ColorCache.getInstance().getColor(200, 224, 255);
private Color mInnerFillBottomBottom_Hover = ColorCache.getInstance().getColor(203, 226, 255);
private Color mInnerFillBottomBottomHighlight_Hover = ColorCache.getInstance().getColor(214, 237, 255);
private Color mTextColorRight = ColorCache.getInstance().getColor(138, 207, 255);
private Color mTextColor = ColorCache.getInstance().getColor(62, 106, 170);
private Color mToolTipMarker = ColorCache.getInstance().getColor(102, 142, 175);
private Color mToolTipMarkerShadow = ColorCache.getInstance().getColor(255, 255, 255);
private Color mToolTipBorder = ColorCache.getInstance().getColor(219, 206, 153);
private Color mToolTipFillTopTop = ColorCache.getInstance().getColor(255, 252, 223);
private Color mToolTipFillTopBottom = ColorCache.getInstance().getColor(255, 239, 167);
private Color mToolTipFillBottomTop = ColorCache.getInstance().getColor(255, 217, 117);
private Color mToolTipFillBottomBottom = ColorCache.getInstance().getColor(255, 227, 152);
private Color mToolTipBorder_Selected = ColorCache.getInstance().getColor(154, 143, 99);
private Color mToolTipFillTopTop_Selected = ColorCache.getInstance().getColor(220, 209, 178);
private Color mToolTipFillTopBottom_Selected = ColorCache.getInstance().getColor(234, 198, 141);
private Color mToolTipFillBottomTop_Selected = ColorCache.getInstance().getColor(255, 167, 56);
private Color mToolTipFillBottomBottom_Selected = ColorCache.getInstance().getColor(255, 204, 78);
private List<AbstractRibbonGroupItem> mToolItems;
private boolean isActiveHoverGroup;
/*
private int mTimeIncreaser = 80;
private int mMaxIterations = 10;
private int mCurrentIteraton = 1;
private Runnable fadeInTimer = null;
private Runnable fadeOutTimer = null;
private boolean mCreated = false;
private boolean mEnableDoubleBuffering = true;
*/
private AbstractRibbonGroupItem mHoverButton;
private AbstractRibbonGroupItem mLastSelectedButton;
private AbstractRibbonGroupItem mLastMouseUpButton;
private List<AbstractRibbonGroupItem> mSelectedButtons;
private RibbonTabComposite mToolBarParent;
private AbstractButtonPaintManager bpm;
private boolean mShowToolTipMarker;
private boolean mToolTipAreaActive;
private boolean mToolTipAreaSelected;
private Rectangle mTooltipArea;
private RibbonTooltip mTooltip;
private RibbonTab mParentTab;
private boolean mIsHoverGroup;
private List<SelectionListener> mSelectionListeners;
private AbstractRibbonGroupItem mMouseDownEscapeButton;
private boolean mFakeMouseDown;
private List<RibbonToolbar> mToolbars;
private List<ITooltipListener> mTooltipListeners;
private Listener deHoverListener;
public RibbonGroup(RibbonTab parent, String groupName) {
super(parent.getFancyToolbar(), SWT.NO_BACKGROUND);
mParentTab = parent;
mToolBarParent = parent.getFancyToolbar();
mGroupName = groupName;
mShowToolTipMarker = false;
parent.getFancyToolbar().groupAdded(this);
init();
}
public RibbonGroup(RibbonTab parent, String groupName, RibbonTooltip toolTip) {
super(parent.getFancyToolbar(), SWT.NO_BACKGROUND);
mParentTab = parent;
mGroupName = groupName;
mToolBarParent = parent.getFancyToolbar();
mToolItems = new ArrayList<AbstractRibbonGroupItem>();
mShowToolTipMarker = (toolTip != null);
mTooltip = toolTip;
parent.getFancyToolbar().groupAdded(this);
init();
}
private void init() {
mToolItems = new ArrayList<AbstractRibbonGroupItem>();
mSelectedButtons = new ArrayList<AbstractRibbonGroupItem>();
mSelectionListeners = new ArrayList<SelectionListener>();
mToolbars = new ArrayList<RibbonToolbar>();
mTooltipListeners = new ArrayList<ITooltipListener>();
// TODO: Extract
bpm = new DefaultButtonPaintManager();
addMouseListener(this);
addMouseTrackListener(this);
addMouseMoveListener(this);
addPaintListener(new PaintListener() {
public void paintControl(PaintEvent pe) {
repaint(pe);
}
});
}
protected void addToolbar(RibbonToolbar tb) {
if (!mToolbars.contains(tb))
mToolbars.add(tb);
updateToolbarBounds();
}
protected void removeToolbar(RibbonToolbar tb) {
mToolbars.remove(tb);
updateToolbarBounds();
}
public void addTooltipListener(ITooltipListener listener) {
if (!mTooltipListeners.contains(listener))
mTooltipListeners.add(listener);
}
public void removeTooltipListener(ITooltipListener listener) {
mTooltipListeners.remove(listener);
}
RibbonTooltip getTooltip(AbstractRibbonGroupItem item, boolean topOrLeft, boolean bottomOrRight) {
for (int i = 0; i < mTooltipListeners.size(); i++) {
RibbonTooltip rt = null;
if (!topOrLeft && !bottomOrRight) {
rt = mTooltipListeners.get(i).getTooltip(item);
}
else if (topOrLeft) {
rt = mTooltipListeners.get(i).getTopOrLeftTooltip(item);
}
else if (bottomOrRight) {
rt = mTooltipListeners.get(i).getBottomOrRightTooltip(item);
}
if (rt != null)
return rt;
}
return null;
}
public RibbonTab getParentTab() {
return mParentTab;
}
public void setTooltip(RibbonTooltip toolTip) {
mShowToolTipMarker = (toolTip != null);
mTooltip = toolTip;
}
public RibbonTooltip getTooltip() {
return mTooltip;
}
public void mouseEnter(MouseEvent e) {
mIsHoverGroup = true;
redraw();
}
public void mouseExit(MouseEvent e) {
// a little trick to not de-hover if the mouse didn't actually exit, but is still somewhere over a native widget
if (!didMouseExit(e.x, e.y))
return;
mIsHoverGroup = false;
deHover();
if (mToolTipAreaActive) {
mToolTipAreaActive = false;
mToolTipAreaSelected = false;
redraw(mTooltipArea.x-1, mTooltipArea.y-1, mTooltipArea.width+2, mTooltipArea.height+2, false);
}
redraw();
}
private boolean didMouseExit(int x, int y) {
if (isInside(x, y, getBounds())) {
// this deals with the problem that the mouse can escape due to the mouse exiting by the help of a menu
// or other widget that blocks us, so if we sense any action outside of us then we dehover and remove
// the listeners added to the display
if (deHoverListener == null) {
deHoverListener = new Listener() {
public void handleEvent(Event event) {
if (!isInside(event.x, event.y, getBounds())) {
mIsHoverGroup = false;
deHover();
redraw();
}
}
};
Display.getDefault().addFilter(SWT.MouseMove, deHoverListener);
Display.getDefault().addFilter(SWT.MouseDown, deHoverListener);
}
return false;
}
return true;
}
public void mouseHover(MouseEvent me) {
if (mTooltipArea != null && mTooltip != null) {
if (isInside(me.x, me.y, mTooltipArea)) {
RibbonTooltipDialog.makeDialog(mTooltip, toDisplay((new Point(mTooltipArea.x, getBounds().height + 5))));
}
}
for (final AbstractRibbonGroupItem item : mToolItems) {
if (item.getBounds() == null)
continue;
if (item instanceof RibbonButton) {
if (isInside(me.x, me.y, item.getBounds())) {
if (item.isSplit()) {
RibbonTooltip tip = null;
if (isInside(me.x, me.y, item.getTopBounds())) {
if (item.getTopOrLeftToolTip() != null)
tip = item.getTopOrLeftToolTip();
else
tip = getTooltip(item, true, false);
}
else if (isInside(me.x, me.y, item.getBottomBounds())) {
if (item.getBottomOrRightToolTip() != null)
tip = item.getBottomOrRightToolTip();
else
tip = getTooltip(item, false, true);
}
if (tip != null) {
RibbonTooltipDialog.makeDialog(tip, toDisplay((new Point(item.getBounds().x, getBounds().height + 5))));
return;
}
}
else {
RibbonTooltip tip = null;
if (item.getToolTip() != null)
tip = item.getToolTip();
else
tip = getTooltip(item, false, false);
if (tip != null) {
RibbonTooltipDialog.makeDialog(item.getToolTip(), toDisplay((new Point(item.getBounds().x, getBounds().height + 5))));
return;
}
}
}
}
else if (item instanceof RibbonButtonGroup) {
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> buttons = rbg.getButtons();
for (AbstractRibbonGroupItem button : buttons) {
if (button.getBounds() == null)
continue;
if (isInside(me.x, me.y, button.getBounds())) {
if (item.isSplit()) {
RibbonTooltip tip = null;
if (isInside(me.x, me.y, item.getTopBounds())) {
if (item.getTopOrLeftToolTip() != null)
tip = item.getTopOrLeftToolTip();
else
tip = getTooltip(item, true, false);
}
else if (isInside(me.x, me.y, item.getBottomBounds())) {
if (item.getBottomOrRightToolTip() != null)
tip = item.getBottomOrRightToolTip();
else
tip = getTooltip(item, false, true);
}
if (tip != null) {
RibbonTooltipDialog.makeDialog(tip, toDisplay((new Point(item.getBounds().x, getBounds().height + 5))));
return;
}
}
else {
RibbonTooltip tip = null;
if (item.getToolTip() != null)
tip = item.getToolTip();
else
tip = getTooltip(item, false, false);
if (tip != null) {
RibbonTooltipDialog.makeDialog(button.getToolTip(), toDisplay((new Point(button.getBounds().x, getBounds().height + 5))));
return;
}
}
}
}
}
}
}
public void mouseDoubleClick(MouseEvent e) {
}
public void mouseDown(MouseEvent me) {
RibbonTooltipDialog.kill();
// as we allow mixing of native widgets they (for example, Buttons and Combos) will retain focus when we click around
// as we aren't actually clicking any new widgets, we're just drawing as if it was true
// therefore - move focus to the group which will remove focus from any native widget (which is the desired effect)
if (Display.getDefault().getFocusControl() != RibbonGroup.this)
setFocus();
if (mTooltipArea != null && isInside(me.x, me.y, mTooltipArea)) {
fireSelection(me);
mToolTipAreaActive = true;
mToolTipAreaSelected = true;
GC gc = new GC(RibbonGroup.this);
drawToolTipMarker(gc);
gc.dispose();
// return;
}
// lets bunch together toolbar buttons with just the normal buttons, code-reuse done easy
List<AbstractRibbonGroupItem> allItemsIncludingToolbar = new ArrayList<AbstractRibbonGroupItem>(mToolItems);
for (RibbonToolbar tb : mToolbars) {
List<RibbonToolbarGrouping> groups = tb.getGroupings();
for (RibbonToolbarGrouping group : groups) {
allItemsIncludingToolbar.addAll(group.getItems());
}
}
for (final AbstractRibbonGroupItem item : allItemsIncludingToolbar) {
if (item.getBounds() == null)
continue;
if (item instanceof RibbonButton) {
if (!item.isEnabled())
continue;
if (isInside(me.x, me.y, item.getBounds())) {
if (!item.isSelected()) {
// button is part of a select group
if (item.getButtonSelectGroup() != null) {
deSelectGroup(item);
item.setSelected(true);
if (!mSelectedButtons.contains(item))
mSelectedButtons.add(item);
Rectangle noow = item.getBounds();
item.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
if (item.isSplit() && !item.isToolbarButton()) {
if (isInside(me.x, me.y, item.getTopBounds())) {
if (!item.isTopSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setTopSelected(true);
}
else
if (isInside(me.x, me.y, item.getBottomBounds())) {
if (!item.isBottomSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setBottomSelected(true);
}
}
else if (item.isToolbarButton()) {
// if split item, determine what part is hover
if ((item.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, item.getLeftBounds())) {
if (!item.isLeftSelected()) {
item.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
// if it's a toggle, untoggle, but only left / top side
if ((item.getStyle() & RibbonButton.STYLE_TOGGLE) != 0) {
if (item.isLeftSelected()) {
item.setLeftSelected(false);
item.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
else
item.setLeftSelected(true);
}
}
if (isInside(me.x, me.y, item.getRightBounds())) {
if (!item.isRightSelected()) {
item.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setRightSelected(true);
}
}
else {
item.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
}
if (!mFakeMouseDown) {
item.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(item, RibbonGroup.this);
mLastSelectedButton = item;
}
}
else {
deSelectSingle(item);
if (!mSelectedButtons.contains(item))
mSelectedButtons.add(item);
item.setSelected(true);
Rectangle noow = item.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
if (item.isSplit() && !item.isToolbarButton()) {
if (isInside(me.x, me.y, item.getTopBounds())) {
if (!item.isTopSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
// if it's a toggle, untoggle, but only left / top side
if ((item.getStyle() & RibbonButton.STYLE_TOGGLE) != 0 && item.isTopSelected()) {
item.setTopSelected(false);
item.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
else
item.setTopSelected(true);
}
else
if (isInside(me.x, me.y, item.getBottomBounds())) {
if (!item.isBottomSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setBottomSelected(true);
}
}
else if (item.isToolbarButton()) {
// if split button, determine what part is hover
if ((item.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, item.getLeftBounds())) {
if (!item.isLeftSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setLeftSelected(true);
}
if (isInside(me.x, me.y, item.getRightBounds())) {
if (!item.isRightSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setRightSelected(true);
}
}
else {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
}
if (!mFakeMouseDown) {
item.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(item, RibbonGroup.this);
mLastSelectedButton = item;
}
}
}
else {
if ((item.getStyle() & RibbonButton.STYLE_TOGGLE) != 0) {
item.setSelected(false);
Rectangle noow = item.getBounds();
boolean any = false;
// scenario: top was selected, so selected would've returned true, but used clicked bottom, deal with that
if (isInside(me.x, me.y, item.getBottomBounds())) {
item.setBottomSelected(true);
any = true;
}
// same thing can happen on small buttons, so right-hand-side bounds apply
if (isInside(me.x, me.y, item.getRightBounds())) {
item.setRightSelected(true);
any = true;
}
if (any) {
item.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(item, RibbonGroup.this);
mLastSelectedButton = item;
}
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
}
}
}
else if (item instanceof RibbonButtonGroup) {
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> buttons = rbg.getButtons();
for (AbstractRibbonGroupItem button : buttons) {
if (!button.isEnabled())
continue;
if (isInside(me.x, me.y, button.getBounds())) {
if (button instanceof RibbonCheckbox) {
if (!button.isEnabled())
continue;
if (isInside(me.x, me.y, button.getBounds())) {
Rectangle noow = button.getBounds();
// flip selection
button.setSelected(!button.isSelected());
// button is part of a select group
if (button.getButtonSelectGroup() != null) {
if (!mSelectedButtons.contains(button))
mSelectedButtons.add(button);
button.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
if (!mFakeMouseDown) {
button.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(button, RibbonGroup.this);
mLastSelectedButton = button;
}
}
else {
if (!mSelectedButtons.contains(button))
mSelectedButtons.add(button);
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
if (!mFakeMouseDown) {
button.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(button, RibbonGroup.this);
mLastSelectedButton = button;
}
}
}
}
else if (button instanceof RibbonButton) { // instanceof else check
// button is part of a select group
if (button.getButtonSelectGroup() != null) {
deSelectGroup(button);
button.setSelected(true);
if (!mSelectedButtons.contains(button))
mSelectedButtons.add(button);
Rectangle noow = button.getBounds();
// if split button, determine what part is hover
if ((button.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, button.getLeftBounds())) {
if (!button.isLeftSelected()) {
button.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
// if it's a toggle, untoggle, but only left / top side
if ((button.getStyle() & RibbonButton.STYLE_TOGGLE) != 0) {
if (button.isLeftSelected()) {
button.setLeftSelected(false);
button.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
else
button.setLeftSelected(true);
}
}
if (isInside(me.x, me.y, button.getRightBounds())) {
if (!button.isRightSelected()) {
button.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
button.setRightSelected(true);
}
}
else {
button.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
if (!mFakeMouseDown) {
button.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(button, RibbonGroup.this);
mLastSelectedButton = button;
}
}
else {
deSelectSingle(button);
// if button style is to not depress, we never flag button as selected for long, see mouseUp()
if ((button.getStyle() & AbstractRibbonGroupItem.STYLE_NO_DEPRESS) == 0) {
if (!mSelectedButtons.contains(button))
mSelectedButtons.add(button);
button.setSelected(true);
}
Rectangle noow = button.getBounds();
// if split button, determine what part is hover
if ((button.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, button.getLeftBounds())) {
if (!button.isLeftSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
button.setLeftSelected(true);
}
if (isInside(me.x, me.y, button.getRightBounds())) {
if (!button.isRightSelected()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
button.setRightSelected(true);
}
}
else {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
if (!mFakeMouseDown) {
button.notifySelectionListeners(me);
mToolBarParent.toolItemSelectionChanged(button, RibbonGroup.this);
mLastSelectedButton = button;
}
}
}
}
}
}
}
}
public void mouseUp(MouseEvent me) {
if (mMouseDownEscapeButton != null) {
mFakeMouseDown = false;
if (isInside(me.x, me.y, mMouseDownEscapeButton.getBottomBounds())) {
mouseDown(me);
}
}
mFakeMouseDown = false;
mMouseDownEscapeButton = null;
// STYLE_NO_DEPRESS and STYLE_ARROW_DOWN_SPLIT buttons depress
for (final AbstractRibbonGroupItem item : mSelectedButtons) {
if (item instanceof RibbonButton) {
if (isInside(me.x, me.y, item.getBounds()))
mLastMouseUpButton = item;
}
else if (item instanceof RibbonButtonGroup) {
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> buttons = rbg.getButtons();
for (AbstractRibbonGroupItem button : buttons) {
if (isInside(me.x, me.y, button.getBounds()))
mLastMouseUpButton = item;
}
}
//if (isInside(me.x, me.y, item.getBounds())) {
if ( ((item.getStyle() & AbstractRibbonGroupItem.STYLE_NO_DEPRESS) != 0) ||
((item.getStyle() & AbstractRibbonGroupItem.STYLE_ARROW_DOWN_SPLIT) != 0) ) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (item.isSplit() && (item.getStyle() & AbstractRibbonGroupItem.STYLE_TOGGLE) != 0) {
if (item.isLeftSelected() || item.isTopSelected()) {
return;
}
}
// if button style is to not depress, we never flag button as selected
item.setSelected(false);
Rectangle noow = item.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
mSelectedButtons.remove(item);
}
});
}
// }
}
// if corner was drawn down
if (mToolTipAreaActive && mTooltipArea != null) {
mToolTipAreaSelected = false;
redraw(mTooltipArea.x, mTooltipArea.y, mTooltipArea.width, mTooltipArea.height, false);
}
}
public void mouseMove(MouseEvent me) {
RibbonTooltipDialog.kill();
// reset cursor, as resize cursor when we're in a RibbonShell can get stuck in the resize-mode despite being far away from the border
if (Display.getDefault().getActiveShell() != null) {
if (Display.getDefault().getActiveShell().getCursor() != null)
Display.getDefault().getActiveShell().setCursor(null);
}
// let's try to mimic an OS feature of "if mouse button is never depressed and mouse moves outside the bounds of the item
// it was originally pressed down on, pretend it's not in focus and was never pressed until mouse is actually released over the button"
// (and if it's not released over the button the item was never truly clicked in the first place, unless it has a menu associated with it)
if (me.stateMask == SWT.BUTTON1) {
if (mHoverButton != null) {
if (!isInside(me.x, me.y, mHoverButton.getBounds())) {
// special case where user clicks a selected button and drags out, we should not de-select, so we cancel the action so to speak
if (mHoverButton.isSelected() && mLastMouseUpButton == mLastSelectedButton)
return;
Rectangle noow = mHoverButton.getBounds();
mMouseDownEscapeButton = mHoverButton;
mHoverButton.setSelected(false);
mHoverButton.setHoverButton(false);
mHoverButton = null;
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
return;
}
if (mMouseDownEscapeButton != null) {
if (isInside(me.x, me.y, mMouseDownEscapeButton.getBounds())) {
mHoverButton = mMouseDownEscapeButton;
// we need to fake a mousedown
try {
mFakeMouseDown = true;
mouseDown(me);
}
catch (Exception err) {
err.printStackTrace();
}
finally {
mFakeMouseDown = false;
}
}
return;
}
}
/* // if we're inside the area...
if (isInside(me.x, me.y, getBounds())) {
// we're not active, we need to fade in
if (!isActiveHover) {
isActiveHover = true;
//fadeIn();
}
}
else {
if (isActiveHover) {
//fadeOut();
isActiveHover = false;
}
}
*/
if (mTooltipArea != null) {
if (isInside(me.x, me.y, mTooltipArea)) {
if (!mToolTipAreaActive) {
mToolTipAreaActive = true;
redraw(mTooltipArea.x-1, mTooltipArea.y-1, mTooltipArea.width+2, mTooltipArea.height+2, false);
return; // we can return as we're 100% not over an item in the toolbar
}
}
else {
if (mToolTipAreaActive) {
mToolTipAreaActive = false;
redraw(mTooltipArea.x-1, mTooltipArea.y-1, mTooltipArea.width+2, mTooltipArea.height+2, false);
}
}
}
// lets bunch together toolbar buttons with just the normal buttons, code-reuse done easy
List<AbstractRibbonGroupItem> allItemsIncludingToolbar = new ArrayList<AbstractRibbonGroupItem>(mToolItems);
for (RibbonToolbar tb : mToolbars) {
List<RibbonToolbarGrouping> groups = tb.getGroupings();
for (RibbonToolbarGrouping group : groups) {
allItemsIncludingToolbar.addAll(group.getItems());
}
}
// check button hovers, redraw old areas exactly (+spacing) where we need to, less flicker
for (AbstractRibbonGroupItem item : allItemsIncludingToolbar) {
if (item.getBounds() == null)
continue;
if (isInside(me.x, me.y, item.getBounds())) {
//System.err.println("Inside group");
if (item instanceof RibbonButton) {
if (!item.isHoverButton()) {
if (mHoverButton != null && mHoverButton != item) {
Rectangle old = mHoverButton.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
}
item.setHoverButton(true);
mHoverButton = item;
mToolBarParent.toolItemHoverChanged(item, RibbonGroup.this);
Rectangle noow = item.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
// if split button, determine what part is hover
if (item.isSplit() && !item.isToolbarButton()) {
if (isInside(me.x, me.y, item.getTopBounds())) {
if (!item.isTopHovered()) {
Rectangle noow = item.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setTopHovered(true);
}
// TODO: We could do an else check... I think
if (isInside(me.x, me.y, item.getBottomBounds())) {
if (!item.isBottomHovered()) {
Rectangle noow = item.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
item.setBottomHovered(true);
}
}
else if (item.isToolbarButton()) {
Rectangle old = mHoverButton.getBounds();
boolean changed = false;
// if split item, determine what part is hover
if ((item.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, item.getLeftBounds())) {
if (!item.isLeftHovered()) {
redraw(old.x-2, old.y, old.width+4, old.height, false);
changed = true;
}
item.setLeftHovered(true);
}
else if (isInside(me.x, me.y, item.getRightBounds())) {
if (!item.isRightHovered()) {
redraw(old.x-2, old.y, old.width+4, old.height, false);
changed = true;
}
item.setRightHovered(true);
}
if (!changed)
continue;
}
}
}
else if (item instanceof RibbonButtonGroup) {
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> buttons = rbg.getButtons();
for (AbstractRibbonGroupItem button : buttons) {
if (isInside(me.x, me.y, button.getBounds())) {
if (button instanceof RibbonCheckbox) {
if (!button.isHoverButton()) {
if (mHoverButton != null && mHoverButton != button) {
Rectangle old = mHoverButton.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
}
button.setHoverButton(true);
mHoverButton = button;
mToolBarParent.toolItemHoverChanged(button, RibbonGroup.this);
Rectangle noow = button.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
}
else {
if (mHoverButton != null && mHoverButton != button) {
Rectangle old = mHoverButton.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
}
if (mHoverButton != null && mHoverButton == button && button.isHoverButton()) {
if (mHoverButton.isSplit()) {
Rectangle old = mHoverButton.getBounds();
boolean changed = false;
// if split button, determine what part is hover
if ((button.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, button.getLeftBounds())) {
if (!button.isLeftHovered()) {
redraw(old.x-2, old.y, old.width+4, old.height, false);
changed = true;
}
button.setLeftHovered(true);
}
else if (isInside(me.x, me.y, button.getRightBounds())) {
if (!button.isRightHovered()) {
redraw(old.x-2, old.y, old.width+4, old.height, false);
changed = true;
}
button.setRightHovered(true);
}
if (!changed)
continue;
}
}
else {
continue;
}
}
mHoverButton = button;
button.setHoverButton(true);
mToolBarParent.toolItemHoverChanged(button, RibbonGroup.this);
Rectangle noow = button.getBounds();
// if split button, determine what part is hover
if ((button.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (isInside(me.x, me.y, button.getLeftBounds())) {
if (!button.isLeftHovered()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
button.setLeftHovered(true);
}
// TODO: We could do an else check... I think
if (isInside(me.x, me.y, button.getRightBounds())) {
if (!button.isRightHovered()) {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
button.setRightHovered(true);
}
}
else {
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
}
}
}
else {
if (button.isHoverButton()) {
if (button.isHoverButton()) {
Rectangle old = button.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
}
button.setHoverButton(false);
mToolBarParent.toolItemHoverChanged(null, RibbonGroup.this);
}
}
}
}
} // isInside() check
else {
if (item instanceof RibbonButton) {
if (item.isHoverButton()) {
Rectangle old = item.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
}
item.setHoverButton(false);
mToolBarParent.toolItemHoverChanged(null, RibbonGroup.this);
}
else if (item instanceof RibbonButtonGroup) {
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> buttons = rbg.getButtons();
for (AbstractRibbonGroupItem button : buttons) {
if (button instanceof RibbonCheckbox) {
if (button.isHoverButton()) {
Rectangle old = button.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
}
button.setHoverButton(false);
mToolBarParent.toolItemHoverChanged(null, RibbonGroup.this);
}
else {
if (button.isHoverButton()) {
mToolBarParent.toolItemHoverChanged(null, RibbonGroup.this);
Rectangle old = button.getBounds();
redraw(old.x-2, old.y, old.width+4, old.height, false);
button.setHoverButton(false);
}
}
}
}
}
}
}
public List<AbstractRibbonGroupItem> getSelection() {
return mSelectedButtons;
}
protected AbstractRibbonGroupItem getHoverItem() {
return mHoverButton;
}
protected void deSelect(AbstractRibbonGroupItem item) {
if (item.getButtonSelectGroup() == null)
deSelectSingle(item);
else
deSelectGroup(item);
}
protected void deSelectGroup(AbstractRibbonGroupItem item) {
if (item == null)
return;
ButtonSelectGroup bsg = item.getButtonSelectGroup();
AbstractRibbonGroupItem oldGroupSelection = bsg.getSelection();
if (oldGroupSelection != null && oldGroupSelection != item) {
oldGroupSelection.setSelected(false);
Rectangle noow = oldGroupSelection.getBounds();
// redraw the right parent! might not be us, we don't limit connected buttons to one visual area
oldGroupSelection.getParent().redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
mSelectedButtons.remove(oldGroupSelection);
}
}
protected void deSelectSingle(AbstractRibbonGroupItem item) {
if (item == null)
return;
item.setSelected(false);
Rectangle noow = item.getBounds();
redraw(noow.x-2, noow.y, noow.width+4, noow.height, false);
mSelectedButtons.remove(item);
}
protected void deHover() {
if (mHoverButton != null) {
Rectangle rect = mHoverButton.getBounds();
redraw(rect.x-4, rect.y, rect.width+8, rect.height, false);
mHoverButton.setHoverButton(false);
mHoverButton = null;
}
// removes any display listeners if there are any
if (deHoverListener != null) {
Display.getDefault().removeFilter(SWT.MouseDown, deHoverListener);
Display.getDefault().removeFilter(SWT.MouseMove, deHoverListener);
deHoverListener = null;
}
/* boolean redraw = false;
for (int i = 0; i < mToolItems.size(); i++) {
if (mToolItems.get(i).isHoverButton()) {
redraw = true;
mToolItems.get(i).setHoverButton(false);
}
}
if (redraw)
redraw();*/
}
// the repaint event, whenever the composite needs to refresh the contents
private void repaint(PaintEvent event) {
GC gc = event.gc;
drawOntoGC(gc);
}
private void drawOntoGC(GC gc) {
//mCurrentIteraton = 0;
//System.err.println("DRAW");
drawGroup(gc);
drawText(gc);
drawToolItems(gc);
drawToolbars(gc);
if (mShowToolTipMarker)
drawToolTipMarker(gc);
}
/* private void fadeIn() {
if (fadeOutTimer != null) {
//System.err.println("Killing fadeout timer!");
Display.getDefault().timerExec(-1, fadeOutTimer);
mCurrentIteraton = 0;
fadeOutTimer = null;
}
fadeInTimer = new Runnable() {
@Override
public void run() {
//System.err.println(" " + mCurrentIteraton);
mCurrentIteraton++;
// widget killed mid-loop
if (FancyToolGroup.this.isDisposed())
return;
GC temp = new GC(FancyToolGroup.this);
fadeIn(temp);
temp.dispose();
if (mCurrentIteraton < mMaxIterations)
Display.getDefault().timerExec(mTimeIncreaser, this);
else {
//System.err.println("End");
mCurrentIteraton = 0;
fadeInTimer = null;
GC temp2 = new GC(FancyToolGroup.this);
paintBackground(temp2);
paintBorder(temp2);
paintText(temp2);
temp2.dispose();
}
}
};
Display.getDefault().timerExec(mTimeIncreaser, fadeInTimer);
}
private void fadeIn(GC gc) {
Rectangle bounds = getBounds();
Color topDark = getBetween(mBlueTop_Dark, mBlueTop_Hover_Dark);
Color topLight = getBetween(mBlueTop_Light, mBlueTop_Hover_Light);
gc.setBackground(topDark);
gc.setForeground(topLight);
gc.fillGradientRectangle(mBorderSize, mBorderSize, bounds.width-mBorderSize, mTopHeight, true);
Color midDark = getBetween(mBlueMid_Dark, mBlueMid_Hover_Dark);
Color midLight = getBetween(mBlueMid_Light, mBlueMid_Hover_Light);
gc.setBackground(midLight);
gc.setForeground(midDark);
gc.fillGradientRectangle(mBorderSize, mBorderSize+mTopHeight, bounds.width-mBorderSize, mMidHeight, true);
Color botDark = getBetween(mBlueBot_Dark, mBlueBot_Hover_Dark);
Color botLight = getBetween(mBlueBot_Light, mBlueBot_Hover_Light);
gc.setBackground(botLight);
gc.setForeground(botDark);
gc.fillGradientRectangle(mBorderSize, mBorderSize+mTopHeight+mMidHeight, bounds.width-mBorderSize, mBotHeight, true);
paintText(gc);
topDark.dispose();
topLight.dispose();
midDark.dispose();
midLight.dispose();
botDark.dispose();
botLight.dispose();
}
private void fadeOut() {
if (fadeInTimer != null) {
//System.err.println("Killing fadein timer!");
Display.getDefault().timerExec(-1, fadeInTimer);
mCurrentIteraton = 0;
fadeInTimer = null;
}
fadeOutTimer = new Runnable() {
@Override
public void run() {
//System.err.println("fading out " + mCurrentIteraton);
mCurrentIteraton++;
// widget killed mid-loop
if (FancyToolGroup.this.isDisposed())
return;
GC temp = new GC(FancyToolGroup.this);
fadeOut(temp);
temp.dispose();
if (mCurrentIteraton < mMaxIterations)
Display.getDefault().timerExec(mTimeIncreaser, this);
else {
//System.err.println("End");
mCurrentIteraton = 0;
fadeOutTimer = null;
GC temp2 = new GC(FancyToolGroup.this);
paintBackground(temp2);
paintBorder(temp2);
paintText(temp2);
temp2.dispose();
}
}
};
Display.getDefault().timerExec(mTimeIncreaser, fadeOutTimer);
}
private void fadeOut(GC gc) {
Rectangle bounds = getBounds();
Color topDark = getBetween(mBlueTop_Hover_Dark, mBlueTop_Dark);
Color topLight = getBetween(mBlueTop_Hover_Light, mBlueTop_Light);
gc.setBackground(topDark);
gc.setForeground(topLight);
gc.fillGradientRectangle(2, mBorderSize, bounds.width-mBorderSize, mTopHeight, true);
Color midDark = getBetween(mBlueMid_Hover_Dark, mBlueMid_Dark);
Color midLight = getBetween(mBlueMid_Hover_Light, mBlueMid_Light);
gc.setBackground(midLight);
gc.setForeground(midDark);
gc.fillGradientRectangle(2, mBorderSize+mTopHeight, bounds.width-mBorderSize, mMidHeight, true);
Color botDark = getBetween(mBlueBot_Hover_Dark, mBlueBot_Dark);
Color botLight = getBetween(mBlueBot_Hover_Light, mBlueBot_Light);
gc.setBackground(botLight);
gc.setForeground(botDark);
gc.fillGradientRectangle(2, mBorderSize+mTopHeight+mMidHeight, bounds.width-mBorderSize, mBotHeight, true);
paintText(gc);
topDark.dispose();
topLight.dispose();
midDark.dispose();
midLight.dispose();
botDark.dispose();
botLight.dispose();
}
// gets a color mixed from two colors where color one is the dark and two is the light
private Color getBetween(Color one, Color two) {
RGB rgbTwo = two.getRGB();
RGB rgbOne = one.getRGB();
int rangeRed = rgbTwo.red - rgbOne.red;
int rangeBlue = rgbTwo.blue - rgbOne.blue;
int rangeGreen = rgbTwo.green - rgbOne.green;
int increaserRed = rangeRed / mMaxIterations;
int increaserBlue = rangeBlue / mMaxIterations;
int increaserGreen = rangeGreen / mMaxIterations;
int finRed = rgbOne.red + (increaserRed * mCurrentIteraton);
int finGreen = rgbOne.green + (increaserGreen * mCurrentIteraton);
int finBlue = rgbOne.blue + (increaserBlue * mCurrentIteraton);
if (finRed > 255)
finRed = 255;
if (finGreen > 255)
finGreen = 255;
if (finBlue > 255)
finBlue = 255;
Color col = new Color(Display.getDefault(), new RGB(
finRed,
finGreen,
finBlue
));
return col;
}
*/
private void drawText(GC gc) {
if (mGroupName == null)
mGroupName = "";
int xWidth = getBounds().width;
Point extent = gc.stringExtent(mGroupName);
int xStart = (xWidth/2) - (extent.x/2);
int yStart = getBounds().height - BUTTON_BOT_HEIGHT - mBorderSize + (BUTTON_BOT_HEIGHT/2) - (extent.y/2);
if (mShowToolTipMarker)
xStart -= 7;
/* gc.setForeground(mTextColorRight);
gc.drawString(mGroupName, xStart+1, yStart, true);
*/ gc.setForeground(mTextColor);
gc.drawString(mGroupName, xStart, yStart, true);
}
private void drawToolItems(GC gc) {
for (AbstractRibbonGroupItem item : mToolItems) {
bpm.drawItem(gc, item);
}
}
private void drawToolbars(GC gc) {
for (RibbonToolbar tb : mToolbars) {
bpm.drawToolbar(gc, tb);
}
}
private void drawGroup(GC gc) {
Rectangle outer = getBounds();
// FIRST OF ALL, WE NEED TO MIMIC THE BACKGROUND OF OUR PARENT WHERE WE ARE
// otherwise we'll get strange transparency and other artifacts left over depending on how we draw
// to make this easy and to ensure exact pixel layover, let's just have the parent paint on us first!
// then we'll just draw wherever we want, how nice!
mToolBarParent.drawOntoGC(gc, outer);
// top line
if (!mIsHoverGroup)
gc.setForeground(mBorderBlueTop);
else
gc.setForeground(mBorderBlueTop_Hover);
gc.drawLine(outer.x+2, 0, outer.x+outer.width-(!mIsHoverGroup ? 4 : 3), 0);
// two pixels in corners, basically same color, but it's 1 pixel shade different, if we care in the future
gc.drawLine(outer.x+1, 1, outer.x+1, 1);
if (!mIsHoverGroup)
gc.drawLine(outer.x+outer.width-3, 1, outer.x+outer.width-3, 1);
else
gc.drawLine(outer.x+outer.width-2, 1, outer.x+outer.width-2, 1);
if (!mIsHoverGroup) {
gc.setForeground(mBorderBlueSideTopTop);
gc.setBackground(mBorderBlueSideTopBottom);
}
else {
gc.setForeground(mBorderBlueSideTopTop_Hover);
gc.setBackground(mBorderBlueSideTopBottom_Hover);
}
gc.fillGradientRectangle(outer.x, 2, 1, 13, true);
// right side differs for hover or not
if (!mIsHoverGroup)
gc.fillGradientRectangle(outer.x+outer.width-2, 2, 1, 13, true);
else
gc.fillGradientRectangle(outer.x+outer.width-1, 2, 1, 13, true);
if (!mIsHoverGroup) {
gc.setForeground(mBorderBlueSideBottomTop);
gc.setBackground(mBorderBlueSideBottomBottom);
}
else {
gc.setForeground(mBorderBlueSideBottomTop_Hover);
gc.setBackground(mBorderBlueSideBottomBottom_Hover);
}
gc.fillGradientRectangle(outer.x, 2+13, 1, 68, true);
if (!mIsHoverGroup)
gc.fillGradientRectangle(outer.x+outer.width-2, 2+13, 1, 68, true);
else
gc.fillGradientRectangle(outer.x+outer.width-1, 2+13, 1, 68, true);
// bottom border and the one remaining pixel in the corner, same deal as above with being 1 pixel in color off, but fix in future or not
if (!mIsHoverGroup)
gc.setForeground(mBorderBlueBottom);
else
gc.setForeground(mBorderBlueBottom_Hover);
gc.drawLine(outer.x+1, 2+13+68, outer.x+1, 2+13+68);
gc.drawLine(outer.x+outer.width-3, 2+13+68, outer.x+outer.width-3, 2+13+68);
// bottom outer
gc.drawLine(outer.x+2, 2+13+68+1, outer.x+outer.width-(!mIsHoverGroup ? 4 : 3), 2+13+68+1);
// INNER BORDER + DROPSHADOW
// top border
if (!mIsHoverGroup)
gc.setForeground(mBorderInnerBlueTop);
else
gc.setForeground(mBorderInnerBlueTop_Hover);
gc.drawLine(outer.x+3, 1, outer.x+outer.width-(!mIsHoverGroup ? 4 : 3), 1);
// FILLS
// now we fill the top part as we need to chomp a pixel off in the top corner of the top fill
if (!mIsHoverGroup) {
gc.setForeground(mInnerFillTopTop);
gc.setBackground(mInnerFillTopBottom);
}
else {
gc.setForeground(mInnerFillTopTop_Hover);
gc.setBackground(mInnerFillTopBottom_Hover);
}
gc.fillGradientRectangle(outer.x+2, 2, outer.width-4, 13, true);
// fill middle part
if (!mIsHoverGroup) {
gc.setForeground(mInnerFillMidTop);
gc.setBackground(mInnerFillMidBottm);
}
else {
gc.setForeground(mInnerFillMidTop_Hover);
gc.setBackground(mInnerFillMidBottm_Hover);
}
gc.fillGradientRectangle(outer.x+2, 2+13, outer.width-4, 54, true);
// fill bottom part
if (!mIsHoverGroup) {
gc.setForeground(mInnerFillBottomTop);
gc.setBackground(mInnerFillBottomBottom);
gc.fillGradientRectangle(outer.x+2, 2+13+54, outer.width-4, 15, true);
}
else {
gc.setForeground(mInnerFillBottomTop_Hover);
gc.setBackground(mInnerFillBottomBottom_Hover);
gc.fillGradientRectangle(outer.x+2, 2+13+54, outer.width-4, 11, true);
gc.setForeground(mInnerFillBottomBottom_Hover);
gc.setBackground(mInnerFillBottomBottomHighlight_Hover);
gc.fillGradientRectangle(outer.x+2, 2+13+54+11, outer.width-4, 4, true);
gc.setForeground(mBorderInnerSideBottomBottom_Hover);
gc.drawLine(outer.x+2, 2+13+54+11+3, outer.x+outer.width-3, 2+13+54+11+3);
}
// INNER LINES
if (!mIsHoverGroup) {
gc.setForeground(mBorderInnerSideTopTop);
gc.setBackground(mBorderInnerSideTopBottom);
}
else {
gc.setForeground(mBorderInnerSideTopTop_Hover);
gc.setBackground(mBorderInnerSideTopBottom_Hover);
}
gc.fillGradientRectangle(outer.x+1, 3, 1, 12, true);
if (!mIsHoverGroup) {
gc.setForeground(mBorderInnerSideMidTop);
gc.setForeground(mBorderInnerSideMidBottom);
}
else {
gc.setForeground(mBorderInnerSideMidTop_Hover);
gc.setForeground(mBorderInnerSideMidBottom_Hover);
}
gc.fillGradientRectangle(outer.x+1, 3+12, 1, 54, true);
if (!mIsHoverGroup) {
gc.setForeground(mBorderInnerSideBottomTop);
gc.setBackground(mBorderInnerSideBottomBottom);
}
else {
gc.setForeground(mBorderInnerSideBottomTop_Hover);
gc.setBackground(mBorderInnerSideBottomBottom_Hover);
}
gc.fillGradientRectangle(outer.x+1, 3+12+54, 1, 14, true);
// SHADOW
if (!mIsHoverGroup) {
gc.setForeground(mShadowTopTop);
gc.setBackground(mShadowTopBottom);
gc.fillGradientRectangle(outer.x+outer.width-1, 2, 1, 13, true);
gc.setForeground(mShadowFadePixel);
gc.drawLine(outer.x+outer.width-1, 2, outer.x+outer.width-1, 2);
gc.setForeground(mShadowMidTop);
gc.setBackground(mShadowMidBottom);
gc.fillGradientRectangle(outer.x+outer.width-1, 2+13, 1, 54, true);
gc.setForeground(mShadowBottomTop);
gc.setBackground(mShadowBottomBottom);
gc.fillGradientRectangle(outer.x+outer.width-1, 2+13+54, 1, 13, true);
}
else {
gc.setForeground(mBorderInnerSideTopTop_Hover);
gc.setBackground(mBorderInnerSideTopBottom_Hover);
gc.fillGradientRectangle(outer.x+outer.width-2, 2, 1, 13, true);
/* gc.setForeground(mShadowFadePixel);
gc.drawLine(outer.x+outer.width-2, 2, outer.x+outer.width-2, 2);
*/
gc.setForeground(mBorderInnerSideMidTop_Hover);
gc.setBackground(mBorderInnerSideMidBottom_Hover);
gc.fillGradientRectangle(outer.x+outer.width-2, 2+13, 1, 54, true);
gc.setForeground(mBorderInnerSideBottomTop_Hover);
gc.setBackground(mBorderInnerSideBottomBottom_Hover);
gc.fillGradientRectangle(outer.x+outer.width-2, 2+13+54, 1, 14, true);
}
// FADED PIXELS IN CORNERS
if (!mIsHoverGroup)
gc.setForeground(mBorderFadePixelTop);
else
gc.setForeground(mBorderFadePixelTop_Hover);
// left top
gc.drawLine(outer.x, 1, outer.x, 1);
gc.drawLine(outer.x+1, 0, outer.x+1, 0);
if (!mIsHoverGroup) {
// right top (is 1 further in towards the left as it has a "drop shadow")
gc.drawLine(outer.x+outer.width-3, 0, outer.x+outer.width-3, 0);
gc.drawLine(outer.x+outer.width-2, 1, outer.x+outer.width-2, 1);
}
else {
gc.drawLine(outer.x+outer.width-2, 0, outer.x+outer.width-2, 0);
gc.drawLine(outer.x+outer.width-1, 1, outer.x+outer.width-1, 1);
}
if (!mIsHoverGroup) {
gc.setForeground(mBorderInnerFadePixelTop);
// left top (there is no right top or bottom right or left, only top left)
gc.drawLine(outer.x+2, 1, outer.x+2, 1);
gc.drawLine(outer.x+1, 2, outer.x+1, 2);
}
// draw bottom corners, same deal as top, but different colors
if (!mIsHoverGroup)
gc.setForeground(mBorderFadePixelBottom);
else
gc.setForeground(mBorderFadePixelBottom_Hover);
// bottom left
gc.drawLine(outer.x, 2+13+68, outer.x, 2+13+68);
gc.drawLine(outer.x+1, 2+13+68+1, outer.x+1, 2+13+68+1);
// bottom right
if (!mIsHoverGroup) {
gc.drawLine(outer.x+outer.width-2, 2+13+68, outer.x+outer.width-2, 2+13+68);
gc.drawLine(outer.x+outer.width-3, 2+13+68+1, outer.x+outer.width-3, 2+13+68+1);
gc.setForeground(mBorderBlueBottom);
gc.drawLine(outer.x+outer.width-3, 2+13+68, outer.x+outer.width-3, 2+13+68);
}
else {
gc.drawLine(outer.x+outer.width-1, 2+13+68, outer.x+outer.width-1, 2+13+68);
gc.drawLine(outer.x+outer.width-2, 2+13+68+1, outer.x+outer.width-2, 2+13+68+1);
gc.setForeground(mBorderBlueBottom_Hover);
gc.drawLine(outer.x+outer.width-2, 2+13+68, outer.x+outer.width-2, 2+13+68);
}
// TODO: (FIX HOW!?) top left corner - truly, as for some reason, transparency is failing for that one pixel, no biggie, but sucks, I hate hacks like this
gc.setForeground(ColorCache.getInstance().getColor(218, 229, 244));
gc.drawLine(outer.x, outer.y, outer.x, outer.y);
}
// TODO: Not exact yet when selected
private void drawToolTipMarker(GC gc) {
Rectangle bounds = getBounds();
int left = bounds.width - 14;
int top = bounds.height - 13;
mTooltipArea = new Rectangle(bounds.width-18, bounds.height-16, 14, 13);
int rectTop = mTooltipArea.y;
int rectLeft = mTooltipArea.x;
int oldAlpha = gc.getAlpha();
if (mToolTipAreaActive) {
if (!mToolTipAreaSelected) {
// draw fill in background
gc.setForeground(mToolTipBorder);
gc.drawRectangle(rectLeft, rectTop, 14, 13);
gc.setForeground(mToolTipFillTopTop);
gc.setBackground(mToolTipFillTopBottom);
gc.fillGradientRectangle(rectLeft+2, rectTop+2, 11, 5, true);
gc.setForeground(mToolTipFillBottomTop);
gc.setBackground(mToolTipFillBottomBottom);
gc.fillGradientRectangle(rectLeft+2, rectTop+2+5, 11, 5, true);
}
else {
gc.setForeground(mToolTipBorder_Selected);
gc.drawRectangle(rectLeft, rectTop, 14, 13);
gc.setForeground(mToolTipFillTopTop_Selected);
gc.setBackground(mToolTipFillTopBottom_Selected);
gc.fillGradientRectangle(rectLeft+1, rectTop+1, 13, 6, true);
gc.setForeground(mToolTipFillBottomTop_Selected);
gc.setBackground(mToolTipFillBottomBottom_Selected);
gc.fillGradientRectangle(rectLeft+1, rectTop+1+6, 13, 6, true);
}
if (mToolTipAreaSelected)
gc.setAlpha(127);
gc.setForeground(mToolTipMarkerShadow);
gc.drawRectangle(rectLeft+1, rectTop+1, 12, 11);
if (mToolTipAreaSelected)
gc.setAlpha(oldAlpha);
}
//TODO: Why don't stickouts draw on select + hover?
// top left
gc.setBackground(mToolTipMarker);
gc.setForeground(mToolTipMarker);
gc.drawLine(left, top, left+5, top);
gc.drawLine(left, top, left, top+5);
// dot
gc.drawLine(left+3, top+3, left+3, top+3);
// square
gc.fillRectangle(left+4, top+4, 3, 3);
// stick-outs
gc.drawLine(left+3, top+6, left+3, top+6);
gc.drawLine(left+6, top+3, left+6, top+3);
// top left
if (mToolTipAreaActive)
gc.setAlpha(127);
gc.setForeground(mToolTipMarkerShadow);
gc.drawLine(left+1, top+1, left+5, top+1);
gc.drawLine(left+1, top+1, left+1, top+5);
// dot
gc.drawLine(left+4, top+3, left+4, top+3);
// square shadow
gc.drawLine(left+7, top+3, left+7, top+3+4);
gc.drawLine(left+4, top+7, left+4+3, top+7);
// reset
if (mToolTipAreaActive || mToolTipAreaSelected)
gc.setAlpha(oldAlpha);
}
/*private void drawBackground(GC gc) {
if (true)
return;
Rectangle bounds = getBounds();
if (isActiveHover) {
gc.setBackground(mBlueTop_Hover_Dark);
gc.setForeground(mBlueTop_Hover_Light);
}
else {
gc.setBackground(mBlueTop_Dark);
gc.setForeground(mBlueTop_Light);
}
gc.fillGradientRectangle(0, mBorderSize, bounds.width-mBorderSize, BUTTON_TOP_HEIGHT, true);
if (isActiveHover) {
gc.setBackground(mBlueMid_Hover_Light);
gc.setForeground(mBlueMid_Hover_Dark);
}
else {
gc.setBackground(mBlueMid_Light);
gc.setForeground(mBlueMid_Dark);
}
gc.fillGradientRectangle(0, mBorderSize+BUTTON_TOP_HEIGHT, bounds.width-mBorderSize, BUTTON_MID_HEIGHT, true);
if (isActiveHover) {
gc.setBackground(mBlueBot_Hover_Light);
gc.setForeground(mBlueBot_Hover_Dark);
}
else {
gc.setBackground(mBlueBot_Light);
gc.setForeground(mBlueBot_Dark);
}
gc.fillGradientRectangle(0, mBorderSize+BUTTON_TOP_HEIGHT+BUTTON_MID_HEIGHT, bounds.width-mBorderSize, BUTTON_BOT_HEIGHT+1, true);
}
*/
protected void toolItemAdded(AbstractRibbonGroupItem ti) {
if (!mToolItems.contains(ti)) {
mToolItems.add(ti);
updateBounds();
redraw();
layout();
}
}
protected void toolItemDisposed(AbstractRibbonGroupItem ti) {
if (mToolItems.contains(ti)) {
mToolItems.remove(ti);
updateBounds();
redraw();
layout();
}
}
protected void updateToolbarBounds() {
for (RibbonToolbar tb : mToolbars) {
List<RibbonToolbarGrouping> groupings = tb.getGroupings();
int rows = tb.getRows();
int topSpacer = 10;
if (rows == 1)
topSpacer = 22;
int rowSpacerVertical = 7;
int row1x = 4;
int row2x = 4;
int row3x = 4;
int row1y = topSpacer;
int row2y = topSpacer + TOOLBAR_BUTTON_HEIGHT + rowSpacerVertical;
int row3y = 0;
if (rows == 3) {
row1y = 2;
row2y = row1y + TOOLBAR_BUTTON_HEIGHT;
row3y = row1y + TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BUTTON_HEIGHT;
}
int buttonHeight = TOOLBAR_BUTTON_HEIGHT;
int buttonWidth = TOOLBAR_BUTTON_WIDTH;
int hSpacer = 0;
int groupHSpacer = 3;
if (tb.getStyle() == RibbonToolbar.STYLE_BORDERED) {
buttonHeight = TOOLBAR_BUTTON_HEIGHT_BORDERED;
buttonWidth = TOOLBAR_BUTTON_WIDTH_BORDERED;
hSpacer = 2;
}
for (int z = 0; z < groupings.size(); z++) {
RibbonToolbarGrouping group = groupings.get(z);
int row = group.getRow();
int x = (row == 1 ? row1x : row == 2 ? row2x : row3x);
int y = (row == 1 ? row1y : row == 2 ? row2y : row3y);
int firstX = x;
// skip the border
x += 2;
int groupWidth = 2;
List<RibbonButton> buttons = group.getItems();
for (int i = 0; i < buttons.size(); i++) {
RibbonButton button = buttons.get(i);
int bStyle = button.getStyle();
if (i == 0)
button.setToolbarSide(RibbonButton.TOOLBAR_SIDE_LEFT);
else if (i == buttons.size() - 1)
button.setToolbarSide(RibbonButton.TOOLBAR_SIDE_RIGHT);
else
button.setToolbarSide(RibbonButton.TOOLBAR_SIDE_NOT_LEFT_OR_RIGHT);
// left and right
if (buttons.size() == 1)
button.setToolbarSide(RibbonButton.TOOLBAR_SIDE_LEFT_AND_RIGHT);
// if arrows are showing we need some extra space
int arrowWidth = 0;
if (((bStyle & RibbonButton.STYLE_ARROW_DOWN) != 0) || (bStyle & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
if (((bStyle & RibbonButton.STYLE_ARROW_DOWN) != 0)) {
arrowWidth += 2; // left spacer
arrowWidth += 5; // arrow width
arrowWidth += 2; // right spacer
}
else {
arrowWidth += 4; // left spacer
arrowWidth += 5; // arrow width
arrowWidth += 2; // right spacer
}
}
// buttons are inside the group bounds, so we push them down by 1px to not share bounds with the border
int finY = y;
if (tb.getStyle() == RibbonToolbar.STYLE_BORDERED)
finY += 1;
button.setBounds(new Rectangle(x, finY, buttonWidth + arrowWidth, buttonHeight));
int addon = buttonWidth + arrowWidth + (i != buttons.size()-1 ? hSpacer : 0);
x += addon;
groupWidth += addon;
}
// remove that border we added above as it is part of us
x -= 2;
groupWidth += 2;
group.setBounds(new Rectangle(firstX, y, groupWidth, buttonHeight));
int spacer = 0;
if (z != groupings.size() - 1)
spacer = groupHSpacer;
switch (row) {
case 1:
row1x += groupWidth + spacer;
break;
case 2:
row2x += groupWidth + spacer;
break;
case 3:
row3x += groupWidth + spacer;
break;
}
} // end group loop
}
}
protected void updateBounds() {
int cur = 4;
int sideSpacerMin = 6;
GC gc = new GC(this);
// set bounds of items
for (AbstractRibbonGroupItem item : mToolItems) {
if (item instanceof RibbonGroupSeparator) {
// spacer + 2 + spacer
item.setBounds(new Rectangle(cur+3, 7, 3+2+3, 55));
cur += 3+2+3;
}
else if (item instanceof RibbonButton) {
// calculate size
String name = item.getName();
if (name == null)
name = "";
int width = 0;
// min width if we have an image is 6px spacer on each side + imge width
int imgWidth = (sideSpacerMin*2) + (item.getImage() == null ? 0 : item.getImage().getBounds().width);
int arrowWidth = 0;
if (((item.getStyle() & RibbonButton.STYLE_ARROW_DOWN) != 0) || (item.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
arrowWidth += 4; // left spacer
arrowWidth += 5; // arrow width
arrowWidth += 8; // right spacer
}
if ((item.getStyle() & RibbonButton.STYLE_TWO_LINE_TEXT) != 0) {
StringTokenizer st = new StringTokenizer(name, "\n");
int maxStrWidth = 0;
int count = 0;
while (st.hasMoreTokens()) {
String token = st.nextToken();
int extentX = gc.stringExtent(token).x;
// account for arrow space if it's an arrow button, which would be on the second row on a split-text button
if (count == 1)
extentX += arrowWidth;
maxStrWidth = Math.max(extentX, maxStrWidth);
count++;
}
maxStrWidth += sideSpacerMin;
width += maxStrWidth;
// what's bigger, our text or our image? use the biggest
width = Math.max(imgWidth, width);
item.setBounds(new Rectangle(cur, 2, width + sideSpacerMin, BUTTON_HEIGHT)); // TODO: Extract 4 (different than above)
cur += width + sideSpacerMin;
}
else {
Point p = gc.stringExtent(name);
width += p.x;
// what's bigger, our text or our image? use the biggest
width = Math.max(imgWidth, width);
item.setBounds(new Rectangle(cur, 2, width + sideSpacerMin, BUTTON_HEIGHT)); // TODO: Extract 4 (different than above)
cur += width + sideSpacerMin;
}
// space them accordingly
cur += BUTTON_SPACING;
}
else if (item instanceof RibbonButtonGroup) {
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> buttons = rbg.getButtons();
int maxWidth = 0;
int maxImgWidth = 0;
int y = 2;
int x = cur;
int MAX_IN_COLUMN = 3;
int verticalCount = 0;
boolean hasCheckboxes = false;
boolean hasButtons = false;
// we calculate the image width based on the widest image or text will not be aligned with image,
// ideally users stick to same-size images, but you never know, and this takes away weird drawing behavior if they are not the same size
for (int i = 0; i < buttons.size(); i++) {
AbstractRibbonGroupItem rb = buttons.get(i);
if (rb.getImage() != null)
maxImgWidth = Math.max(maxImgWidth, rb.getImage().getBounds().width);
if (rb instanceof RibbonButton)
hasButtons = true;
else if (rb instanceof RibbonCheckbox)
hasCheckboxes = true;
}
boolean mixOfBoth = hasButtons && hasCheckboxes;
// loop again
for (int i = 0; i < buttons.size(); i++) {
AbstractRibbonGroupItem rb = buttons.get(i);
verticalCount++;
int width = 0;
if (rb instanceof RibbonCheckbox) {
y += 4; // checkboxes are 4px down always, as they are different sizes than for example buttons
width = 13;
width += 6; // spacer between box and text
String name = rb.getName();
if (name == null)
name = "";
width += gc.stringExtent(name).x;
width += sideSpacerMin;
// if checkbuttons are mixed with buttons, checkboxes need a 1px further-to-the-right alignment
// MS never seems to do this in Office, but I guess it could be possible
int extra = mixOfBoth ? 1 : 0;
rb.setBounds(new Rectangle(x+3+extra, y, width-1, CHECKBOX_HEIGHT));
y += CHECKBOX_HEIGHT + 5;
maxWidth = Math.max(width, maxWidth);
}
else {
width = maxImgWidth;
width += 2; // img spacer, same regardless of button
// calculate size
String name = rb.getName();
if (name == null)
name = "";
Point p = gc.stringExtent(name);
width += p.x; // text width
// check if this item has an arrow attached to it
if ( ((rb.getStyle() & RibbonButton.STYLE_ARROW_DOWN) != 0) || ((rb.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0)) {
width += 4; // spacer
width += 5; // actual arrow
width += 8; // right spacer
// we'll need another bit of spacing if it's split and arrow
if ((rb.getStyle() & RibbonButton.STYLE_ARROW_DOWN_SPLIT) != 0) {
width += 2;
}
}
else {
width += 8; // right spacer, border width is ~2px
}
rb.setBounds(new Rectangle(x, y, width, 22)); // TODO: Extract 4 (different than above), and 22
y += 22;
maxWidth = Math.max(width, maxWidth);
}
if (verticalCount % MAX_IN_COLUMN == 0) {
y = 2;
x += maxWidth+1;
verticalCount = 0;
}
}
rbg.setBounds(new Rectangle(cur, 2, x+maxWidth, BUTTON_HEIGHT)); // TODO: Extract 4 (different than above)
cur += maxWidth;
}
}
gc.dispose();
}
protected void toolItemRemoved(AbstractRibbonGroupItem ti) {
mToolItems.remove(ti);
redraw();
}
private boolean isInside(int x, int y, Rectangle rect) {
if (rect == null) {
return false;
}
return x >= rect.x && y >= rect.y && x <= (rect.x + rect.width-1) && y <= (rect.y + rect.height-1);
}
@Override
public Rectangle getBounds() {
int toolWidths = 0;
int normalControlMaxWidth = 0;
int normalControlBorderSpacer = mBorderSize * 2;
// deal with native widgets inside our groups
Control [] subItems = getChildren();
for (int i = 0; i < subItems.length; i++) {
Control item = subItems[i];
Point size = item.computeSize(SWT.DEFAULT, SWT.DEFAULT);
if (normalControlMaxWidth == 0)
normalControlMaxWidth = normalControlBorderSpacer;
normalControlMaxWidth = Math.max(normalControlMaxWidth, size.x + normalControlBorderSpacer);
}
// TODO: Bigger todo, we need to be smart about max 3 items height-wise for small items, we need layouts...
for (int i = 0; i < mToolItems.size(); i++) {
AbstractRibbonGroupItem item = mToolItems.get(i);
if (item.getBounds() == null)
continue;
if (item instanceof RibbonButton)
toolWidths += item.getBounds().width;
else if (item instanceof RibbonCheckbox)
toolWidths = Math.max(toolWidths, item.getBounds().width);
else if (item instanceof RibbonButtonGroup) {
//toolWidths += item.getBounds().width;
RibbonButtonGroup rbg = (RibbonButtonGroup) item;
List<AbstractRibbonGroupItem> items = rbg.getButtons();
int maxWidth = 0;
// width = button.x + button.width - group.x
for (AbstractRibbonGroupItem button : items) {
maxWidth = Math.max(button.getBounds().x+button.getBounds().width-rbg.getBounds().x, maxWidth);
}
toolWidths += maxWidth;//button.getBounds().width;
}
else
toolWidths += item.getBounds().width;
if (i != mToolItems.size()-1)
toolWidths += BUTTON_SPACING;
}
int widestToolbar = 0;
for (int i = 0; i < mToolbars.size(); i++) {
RibbonToolbar tb = mToolbars.get(i);
boolean bordered = (tb.getStyle() == RibbonToolbar.STYLE_BORDERED);
int minX = 0;
int maxX = 0;
List<RibbonToolbarGrouping> groups = tb.getGroupings();
for (RibbonToolbarGrouping group : groups) {
minX = Math.min(minX, group.getBounds().x);
maxX = Math.max(maxX, group.getBounds().x + group.getBounds().width - (bordered ? 4 : 0));
}
widestToolbar = Math.max(widestToolbar, maxX-minX);
}
if (widestToolbar > toolWidths)
toolWidths = widestToolbar;
if (toolWidths < normalControlMaxWidth)
toolWidths = normalControlMaxWidth;
// check how long the group name is, we don't truncate it
if (mGroupName != null) {
GC gc = new GC(this);
int w = gc.stringExtent(mGroupName).x;
if (mShowToolTipMarker)
w += 15 + 4; // office uses a 4px spacer for tooltip space between marker and text
gc.dispose();
if (w > toolWidths)
toolWidths = w;
}
int extra = 1; // TODO: figure out what px is missing, until then, space by 1
//if (mGroupName.equals("Checkboxes"))
//System.err.println(mGroupName + " " + toolWidths + " " + (mBorderSize*2) + " 4 " + extra);
return new Rectangle(0, 0, toolWidths+(mBorderSize*2)+4+extra, 85);
}
@Override
public boolean isVisible() {
return mVisible;
}
public void setVisible(boolean visible) {
mVisible = visible;
}
public void addSelectionListener(SelectionListener listener) {
if (!mSelectionListeners.contains(listener))
mSelectionListeners.add(listener);
}
public void removeSelectionListener(SelectionListener listener) {
mSelectionListeners.remove(listener);
}
protected void fireSelection(MouseEvent me) {
Event e = new Event();
e.x = me.x;
e.y = me.y;
e.data = me.data;
e.widget = me.widget;
e.stateMask = me.stateMask;
e.button = me.button;
SelectionEvent se = new SelectionEvent(e);
for (SelectionListener listener : mSelectionListeners)
listener.widgetSelected(se);
}
@Override
public void dispose() {
for (int i = 0; i < mToolItems.size(); i++)
mToolItems.get(i).dispose();
mToolItems.clear();
super.dispose();
}
void removeButton(AbstractRibbonGroupItem item) {
mToolItems.remove(item);
}
/*
class GroupLayout extends Layout {
@Override
protected Point computeSize(Composite composite, int hint, int hint2, boolean flushCache) {
return null;
}
@Override
protected void layout(Composite composite, boolean flushCache) {
int innerTopSpacing = 8;
int innerLeftSpacing = 3;
Control [] subItems = composite.getChildren();
for (int i = 0; i < subItems.length; i++) {
Control item = subItems[i];
item.setLocation(innerLeftSpacing, innerTopSpacing);
Point size = item.computeSize(SWT.DEFAULT, SWT.DEFAULT);
item.setBounds(rect)
}
}
}*/
}