From 5a372d0f90ec04d8c573e4e20ab0c3911a469164 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 2 Dec 2021 16:26:47 +0100 Subject: [PATCH 1/8] add first elements --- .../icons/bullet_left.png | Bin 0 -> 307 bytes .../icons/bullet_right.png | Bin 0 -> 307 bytes .../ui/swt/internal/HorizontalSpinner.java | 1113 +++++++++++++++++ .../ui/swt/internal/WaveformSlider.java | 95 ++ .../ui/swt/internal/WaveformView.java | 22 +- .../ui/swt/internal/ZoomingScrollbar.java | 108 ++ .../database/ui/swt/sb/ActionScheduler.java | 18 + .../database/ui/swt/sb/ButtonClick.java | 45 + .../database/ui/swt/sb/ClickControl.java | 98 ++ .../ui/swt/sb/ComponentDistribution.java | 105 ++ .../database/ui/swt/sb/Decrementer.java | 24 + .../database/ui/swt/sb/Direction.java | 203 +++ .../database/ui/swt/sb/DragControl.java | 105 ++ .../database/ui/swt/sb/DragDetector.java | 60 + .../database/ui/swt/sb/DragShifter.java | 59 + .../database/ui/swt/sb/FastDecrementer.java | 49 + .../database/ui/swt/sb/FastIncrementer.java | 42 + .../database/ui/swt/sb/FlatScrollBar.java | 295 +++++ .../ui/swt/sb/FlatScrollBarLayout.java | 23 + .../database/ui/swt/sb/ImageDrawer.java | 109 ++ .../database/ui/swt/sb/ImageUpdate.java | 46 + .../database/ui/swt/sb/Incrementer.java | 24 + .../ui/swt/sb/MouseDownActionTimer.java | 37 + .../database/ui/swt/sb/MouseTracker.java | 66 + .../database/ui/swt/sb/MouseWheelShifter.java | 69 + .../database/ui/swt/sb/ResizeObserver.java | 19 + .../database/ui/swt/sb/ShiftData.java | 32 + .../ui/swt/sb/UntypedSelectionAdapter.java | 43 + .../database/ui/swt/sb/ViewComponent.java | 7 + .../org/eclipse/wb/swt/ResourceManager.java | 438 +++++++ .../eclipse/wb/swt/SWTResourceManager.java | 267 ++-- .../scviewer.product | 1 - 32 files changed, 3490 insertions(+), 132 deletions(-) create mode 100644 plugins/com.minres.scviewer.database.ui.swt/icons/bullet_left.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/icons/bullet_right.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/HorizontalSpinner.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformSlider.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ActionScheduler.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ButtonClick.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ClickControl.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ComponentDistribution.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Decrementer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Direction.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragControl.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragDetector.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragShifter.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastDecrementer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastIncrementer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBar.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBarLayout.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageDrawer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageUpdate.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Incrementer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseDownActionTimer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseTracker.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseWheelShifter.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ResizeObserver.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ShiftData.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/UntypedSelectionAdapter.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ViewComponent.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/ResourceManager.java diff --git a/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_left.png b/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_left.png new file mode 100644 index 0000000000000000000000000000000000000000..96b446605ebf85c7142eb9ec096460ba2a9b330a GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~Unv^o$cHPZFwf!uL_esT;#rYmU(lg^$`c4sSKX3elF{r5}E*Evu=$5 literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_right.png b/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_right.png new file mode 100644 index 0000000000000000000000000000000000000000..e809d370116b96a15258bb1e0551101f8bc2d74d GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~f)_POe%sw|Iw383oe`7fwavx4 q6W*+l74C_@$!4K{RdLdXyWCG1nK!En^U45CW$<+Mb6Mw<&;$VPI%^*Q literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/HorizontalSpinner.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/HorizontalSpinner.java new file mode 100644 index 0000000..521bb8d --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/HorizontalSpinner.java @@ -0,0 +1,1113 @@ +package com.minres.scviewer.database.ui.swt.internal; + +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Text; + +/** + * Instances of this class are selectable user interface objects that allow the + * user to enter and modify numeric values. + *

+ *

+ *
Styles:
+ *
READ_ONLY, FLAT
+ *
Events:
+ *
Selection, Modify
+ *
+ *

+ */ +public class HorizontalSpinner extends Composite { + + private enum ALIGNMENT { + LEFT, RIGHT, BOTH + }; + + private final List modifyListeners = new ArrayList(); + + private Button leftButton; + private Button rightButton; + private Text text; + private int digits = 0; + private int increment = 1; + private int maximum = 0; + private int minimum = 255; + private int pageIncrement = 10; + private int storedValue = 0; + private ALIGNMENT alignment = ALIGNMENT.BOTH; + + private final char decimalFormatSeparator; + + /** + * Constructs a new instance of this class given its parent and a style + * value describing its behavior and appearance. + *

+ * The style value is either one of the style constants defined in class + * SWT which is applicable to instances of this class, or must + * be built by bitwise OR'ing together (that is, using the + * int "|" operator) two or more of those SWT + * style constants. The class description lists the style constants that are + * applicable to the class. Style bits are also inherited from superclasses. + *

+ * + * @param parent a composite control which will be the parent of the new + * instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the parent
  • + *
  • ERROR_INVALID_SUBCLASS - if this class is not an + * allowed subclass
  • + *
+ * + * @see SWT#READ_ONLY + * @see SWT#FLAT + */ + public HorizontalSpinner(final Composite parent, final int style) { + super(parent, style); + + if ((style & SWT.LEFT) == SWT.LEFT) { + alignment = ALIGNMENT.LEFT; + } + + if ((style & SWT.RIGHT) == SWT.RIGHT) { + alignment = ALIGNMENT.RIGHT; + } + + final GridLayout gd = new GridLayout(3, false); + gd.horizontalSpacing = gd.verticalSpacing = 0; + gd.marginWidth = gd.marginHeight = 0; + setLayout(gd); + + createContent(style); + addTextListeners(); + addButtonsListener(); + addModifyListeners(); + + decimalFormatSeparator = new DecimalFormatSymbols().getDecimalSeparator(); + } + + /** + * Create the content of the widget + * + * @param style style of the widget + */ + private void createContent(final int style) { + final boolean readOnly = (style & SWT.READ_ONLY) == SWT.READ_ONLY; + final boolean flat = (style & SWT.FLAT) == SWT.FLAT; + final int buttonStyle = SWT.ARROW | (flat ? SWT.FLAT : SWT.NONE); + + if (alignment == ALIGNMENT.BOTH) { + createMinusButton(buttonStyle); + createText(readOnly); + createPlusButton(buttonStyle); + } else if (alignment == ALIGNMENT.LEFT) { + createMinusButton(buttonStyle); + createPlusButton(buttonStyle); + createText(readOnly); + } else { + createText(readOnly); + createMinusButton(buttonStyle); + createPlusButton(buttonStyle); + } + } + + /** + * Create minus button + * + * @param buttonStyle button style + */ + private void createMinusButton(final int buttonStyle) { + leftButton = new Button(this, buttonStyle | SWT.LEFT); + leftButton.setFont(getFont()); + leftButton.setBackground(getBackground()); + leftButton.setCursor(getCursor()); + leftButton.setEnabled(getEnabled()); + leftButton.setFont(getFont()); + leftButton.setForeground(getForeground()); + leftButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false)); + } + + /** + * Create the text zone + * + * @param readOnly if true, the text is read only + */ + private void createText(final boolean readOnly) { + text = new Text(this, readOnly ? SWT.READ_ONLY : SWT.NONE); + final GridData gd = new GridData(GridData.FILL, GridData.CENTER, true, false); + gd.minimumWidth = 40; + text.setLayoutData(gd); + } + + /** + * Create plus button + * + * @param buttonStyle button style + */ + private void createPlusButton(final int buttonStyle) { + rightButton = new Button(this, buttonStyle | SWT.RIGHT); + rightButton.setFont(getFont()); + rightButton.setBackground(getBackground()); + rightButton.setCursor(getCursor()); + rightButton.setEnabled(getEnabled()); + rightButton.setFont(getFont()); + rightButton.setForeground(getForeground()); + rightButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false)); + } + + /** + * Add the text listeners + */ + private void addTextListeners() { + text.addListener(SWT.Verify, e -> { + if (e.character != 0 && !(Character.isDigit(e.character) || e.character == '-') && e.keyCode != SWT.BS && e.keyCode != SWT.DEL) { + e.doit = false; + return; + } + e.doit = verifyEntryAndStoreValue(e.text, e.keyCode); + }); + + text.addListener(SWT.KeyUp, e -> { + if (e.keyCode == SWT.ARROW_UP) { + increaseValue(increment); + } + if (e.keyCode == SWT.ARROW_DOWN) { + decreaseValue(increment); + } + if (e.keyCode == SWT.PAGE_UP) { + increaseValue(pageIncrement); + } + if (e.keyCode == SWT.PAGE_DOWN) { + decreaseValue(pageIncrement); + } + + }); + + text.addListener(SWT.FocusOut, e -> { + if (text.getText().trim().equals("")) { + setSelection(storedValue); + } + }); + } + + /** + * Verify the entry and store the value in the field storedValue + * + * @param entry entry to check + * @param keyCode code of the typed key + * @return true if the entry if correct, false + * otherwise + */ + private boolean verifyEntryAndStoreValue(final String entry, final int keyCode) { + + return true; + } + + /** + * Add the listener to the buttons + */ + private void addButtonsListener() { + leftButton.addListener(SWT.Selection, e -> { + decreaseValue(increment); + }); + + rightButton.addListener(SWT.Selection, e -> { + increaseValue(increment); + }); + + } + + /** + * Increase the value stored in this snippet + * + * @param value value to increase + */ + private void increaseValue(final int value) { + setSelection(getSelection() + value); + + } + + /** + * Decrease the value stored in this snippet + * + * @param value value to decrease + */ + private void decreaseValue(final int value) { + setSelection(getSelection() - value); + } + + /** + * Add the modify listeners + */ + private void addModifyListeners() { + text.addModifyListener(e -> { + for (final ModifyListener m : modifyListeners) { + m.modifyText(e); + } + }); + + } + + /** + * Adds the listener to the collection of listeners who will be notified + * when the receiver's text is modified, by sending it one of the messages + * defined in the ModifyListener interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see ModifyListener + * @see #removeModifyListener + * @see org.eclipse.swt.widgets.Spinner#addModifyListener(org.eclipse.swt.events.ModifyListener) + */ + + public void addModifyListener(final ModifyListener listener) { + checkWidget(); + modifyListeners.add(listener); + } + + /** + * Adds the listener to the collection of listeners who will be notified + * when the control is selected by the user, by sending it one of the + * messages defined in the SelectionListener interface. + *

+ * widgetSelected is not called for texts. + * widgetDefaultSelected is typically called when ENTER is + * pressed in a single-line text. + *

+ * + * @param listener the listener which should be notified when the control is + * selected by the user + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ + public void addSelectionListener(final SelectionListener listener) { + checkWidget(); + } + + /** + * Copies the selected text. + *

+ * The current selection is copied to the clipboard. + *

+ * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void copy() { + checkWidget(); + text.copy(); + } + + /** + * Cuts the selected text. + *

+ * The current selection is first copied to the clipboard and then deleted + * from the widget. + *

+ * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void cut() { + checkWidget(); + text.cut(); + } + + /** + * Returns the number of decimal places used by the receiver. + * + * @return the digits + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getDigits() { + checkWidget(); + return digits; + } + + /** + * Returns the amount that the receiver's value will be modified by when the + * up/down arrows are pressed. + * + * @return the increment + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getIncrement() { + checkWidget(); + return increment; + } + + /** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getMaximum() { + checkWidget(); + return maximum; + } + + /** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getMinimum() { + checkWidget(); + return minimum; + } + + /** + * Returns the amount that the receiver's position will be modified by when + * the page up/down keys are pressed. + * + * @return the page increment + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getPageIncrement() { + checkWidget(); + return pageIncrement; + } + + /** + * Returns the selection, which is the receiver's position. + * + * @return the selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getSelection() { + checkWidget(); + return storedValue; + } + + /** + * Returns a string containing a copy of the contents of the receiver's text + * field, or an empty string if there are no contents. + * + * @return the receiver's text + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + */ + public String getText() { + checkWidget(); + return text.getText(); + } + + /** + * Returns the maximum number of characters that the receiver's text field + * is capable of holding. If this has not been changed by + * setTextLimit(), it will be the constant + * Spinner.LIMIT. + * + * @return the text limit + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see #LIMIT + */ + public int getTextLimit() { + checkWidget(); + return text.getTextLimit(); + } + + /** + * Pastes text from clipboard. + *

+ * The selected text is deleted from the widget and new text inserted from + * the clipboard. + *

+ * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void paste() { + checkWidget(); + text.paste(); + } + + /** + * Removes the listener from the collection of listeners who will be + * notified when the receiver's text is modified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see ModifyListener + * @see #addModifyListener + */ + public void removeModifyListener(final ModifyListener listener) { + checkWidget(); + modifyListeners.remove(listener); + } + + /** + * Removes the listener from the collection of listeners who will be + * notified when the control is selected by the user. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see SelectionListener + * @see #addSelectionListener + */ + public void removeSelectionListener(final SelectionListener listener) { + checkWidget(); + } + + /** + * Sets the number of decimal places used by the receiver. + *

+ * The digit setting is used to allow for floating point values in the + * receiver. For example, to set the selection to a floating point value of + * 1.37 call setDigits() with a value of 2 and setSelection() with a value + * of 137. Similarly, if getDigits() has a value of 2 and getSelection() + * returns 137 this should be interpreted as 1.37. This applies to all + * numeric APIs. + *

+ * + * @param value the new digits (must be greater than or equal to zero) + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_INVALID_ARGUMENT - if the value is less than + * zero
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setDigits(final int value) { + checkWidget(); + digits = value; + convertSelectionToStringValue(); + } + + /** + * Sets the amount that the receiver's value will be modified by when the + * up/down arrows are pressed to the argument, which must be at least one. + * + * @param value the new increment (must be greater than zero) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setIncrement(final int value) { + checkWidget(); + increment = value; + } + + /** + * Sets the maximum value that the receiver will allow. This new value will + * be ignored if it is less than the receiver's current minimum value. If + * the new maximum is applied then the receiver's selection value will be + * adjusted if necessary to fall within its new range. + * + * @param value the new maximum, which must be greater than or equal to the + * current minimum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setMaximum(final int value) { + checkWidget(); + maximum = value; + } + + /** + * Sets the minimum value that the receiver will allow. This new value will + * be ignored if it is greater than the receiver's current maximum value. If + * the new minimum is applied then the receiver's selection value will be + * adjusted if necessary to fall within its new range. + * + * @param value the new minimum, which must be less than or equal to the + * current maximum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setMinimum(final int value) { + checkWidget(); + minimum = value; + } + + /** + * Sets the amount that the receiver's position will be modified by when the + * page up/down keys are pressed to the argument, which must be at least + * one. + * + * @param value the page increment (must be greater than zero) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setPageIncrement(final int value) { + checkWidget(); + pageIncrement = value; + } + + /** + * Sets the selection, which is the receiver's position, to the + * argument. If the argument is not within the range specified by minimum + * and maximum, it will be adjusted to fall within this range. + * + * @param value the new selection (must be zero or greater) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setSelection(int selection) { + checkWidget(); + if (selection < minimum) { + selection = minimum; + } else if (selection > maximum) { + selection = maximum; + } + + storedValue = selection; + text.setText(convertSelectionToStringValue()); + } + + /** + * Convert the selection into a string + * + * @return the string representation of the selection + */ + private String convertSelectionToStringValue() { + if (getDigits() == 0) { + return String.valueOf(storedValue); + } + final StringBuilder unformatted = new StringBuilder(String.valueOf(storedValue * Math.pow(10, -1 * getDigits()))); + for (int i = 0; i < digits; i++) { + unformatted.append("0"); + } + final int position = unformatted.indexOf("."); + final String temp = unformatted.substring(0, position + 1 + digits); + return temp.replace('.', decimalFormatSeparator); + + } + + /** + * Sets the maximum number of characters that the receiver's text field is + * capable of holding to be the argument. + *

+ * To reset this value to the default, use + * setTextLimit(Spinner.LIMIT). Specifying a limit value larger + * than Spinner.LIMIT sets the receiver's limit to + * Spinner.LIMIT. + *

+ * + * @param limit new text limit + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_CANNOT_BE_ZERO - if the limit is zero
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see #LIMIT + */ + public void setTextLimit(final int limit) { + checkWidget(); + text.setTextLimit(limit); + } + + /** + * Sets the receiver's selection, minimum value, maximum value, digits, + * increment and page increment all at once. + *

+ * Note: This is similar to setting the values individually using the + * appropriate methods, but may be implemented in a more efficient fashion + * on some platforms. + *

+ * + * @param selection the new selection value + * @param minimum the new minimum value + * @param maximum the new maximum value + * @param digits the new digits value + * @param increment the new increment value + * @param pageIncrement the new pageIncrement value + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setValues(final int selection, final int minimum, final int maximum, final int digits, final int increment, final int pageIncrement) { + setMinimum(minimum); + setMaximum(maximum); + setDigits(digits); + setIncrement(increment); + setPageIncrement(pageIncrement); + setSelection(selection); + } + + /** + * Sets the receiver's drag detect state. If the argument is + * true, the receiver will detect drag gestures, otherwise + * these gestures will be ignored. + * + * @param dragDetect the new drag detect state + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public boolean setFocus() { + checkWidget(); + return text.setFocus(); + } + + /** + * Forces the receiver to have the keyboard focus, causing all + * keyboard events to be delivered to it. + * + * @return true if the control got focus, and + * false if it was unable to. + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see #setFocus + */ + @Override + public boolean forceFocus() { + checkWidget(); + return text.forceFocus(); + } + + /** + * Sets the receiver's background color to the color specified by the + * argument, or to the default system color for the control if the argument + * is null. + *

+ * Note: This operation is a hint and may be overridden by the platform. For + * example, on Windows the background of a Button cannot be changed. + *

+ * + * @param color the new color (or null) + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_INVALID_ARGUMENT - if the argument has been + * disposed
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setBackground(final Color color) { + super.setBackground(color); + leftButton.setBackground(color); + rightButton.setBackground(color); + text.setBackground(color); + } + + /** + * Sets the receiver's background image to the image specified by the + * argument, or to the default system color for the control if the argument + * is null. The background image is tiled to fill the available space. + *

+ * Note: This operation is a hint and may be overridden by the platform. For + * example, on Windows the background of a Button cannot be changed. + *

+ * + * @param image the new image (or null) + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_INVALID_ARGUMENT - if the argument has been + * disposed
  • + *
  • ERROR_INVALID_ARGUMENT - if the argument is not a + * bitmap
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setBackgroundImage(final Image image) { + super.setBackgroundImage(image); + leftButton.setBackgroundImage(image); + rightButton.setBackgroundImage(image); + text.setBackgroundImage(image); + + } + + /** + * Sets the receiver's cursor to the cursor specified by the argument, or to + * the default cursor for that kind of control if the argument is null. + *

+ * When the mouse pointer passes over a control its appearance is changed to + * match the control's cursor. + *

+ * + * @param cursor the new cursor (or null) + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_INVALID_ARGUMENT - if the argument has been + * disposed
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setCursor(final Cursor cursor) { + super.setCursor(cursor); + leftButton.setCursor(cursor); + rightButton.setCursor(cursor); + text.setCursor(cursor); + } + + /** + * Enables the receiver if the argument is true, and disables + * it otherwise. A disabled control is typically not selectable from the + * user interface and draws with an inactive or "grayed" look. + * + * @param enabled the new enabled state + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setEnabled(final boolean enabled) { + super.setEnabled(enabled); + leftButton.setEnabled(enabled); + rightButton.setEnabled(enabled); + text.setEnabled(enabled); + } + + /** + * Sets the font that the receiver will use to paint textual information to + * the font specified by the argument, or to the default font for that kind + * of control if the argument is null. + * + * @param font the new font (or null) + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_INVALID_ARGUMENT - if the argument has been + * disposed
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setFont(final Font font) { + super.setFont(font); + text.setFont(font); + } + + /** + * Sets the receiver's foreground color to the color specified by the + * argument, or to the default system color for the control if the argument + * is null. + *

+ * Note: This operation is a hint and may be overridden by the platform. + *

+ * + * @param color the new color (or null) + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_INVALID_ARGUMENT - if the argument has been + * disposed
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setForeground(final Color color) { + super.setForeground(color); + leftButton.setForeground(color); + rightButton.setForeground(color); + text.setForeground(color); + } + + /** + * Sets the receiver's pop up menu to the argument. All controls may + * optionally have a pop up menu that is displayed when the user requests + * one for the control. The sequence of key strokes, button presses and/or + * button releases that are used to request a pop up menu is platform + * specific. + *

+ * Note: Disposing of a control that has a pop up menu will dispose of the + * menu. To avoid this behavior, set the menu to null before the control is + * disposed. + *

+ * + * @param menu the new pop up menu + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu
  • + *
  • ERROR_INVALID_PARENT - if the menu is not in the same + * widget tree
  • + *
  • ERROR_INVALID_ARGUMENT - if the menu has been disposed + *
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setMenu(final Menu menu) { + super.setMenu(menu); + leftButton.setMenu(menu); + rightButton.setMenu(menu); + text.setMenu(menu); + } + + /** + * Sets the receiver's tool tip text to the argument, which may be null + * indicating that the default tool tip for the control will be shown. For a + * control that has a default tool tip, such as the Tree control on Windows, + * setting the tool tip text to an empty string replaces the default, + * causing no tool tip text to be shown. + *

+ * The mnemonic indicator (character '&') is not displayed in a tool + * tip. To display a single '&' in the tool tip, the character '&' + * can be escaped by doubling it in the string. + *

+ * + * @param string the new tool tip text (or null) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + @Override + public void setToolTipText(final String tooltipText) { + super.setToolTipText(tooltipText); + leftButton.setToolTipText(tooltipText); + rightButton.setToolTipText(tooltipText); + text.setToolTipText(tooltipText); + } + +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformSlider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformSlider.java new file mode 100644 index 0000000..20c909a --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformSlider.java @@ -0,0 +1,95 @@ +package com.minres.scviewer.database.ui.swt.internal; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Slider; +import org.eclipse.wb.swt.SWTResourceManager; + +public class WaveformSlider extends Composite { + + Slider slider; + + Color buttonColor; + + public WaveformSlider(Composite parent, int style) { + super(parent, style); + GridLayout gridLayout = new GridLayout(3, false); + gridLayout.horizontalSpacing = 0; + gridLayout.verticalSpacing = 0; + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + setLayout(gridLayout); + + buttonColor = getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY); + + Button scrlLeft = new Button(this, /*SWT.BORDER |*/ SWT.FLAT | SWT.CENTER); + scrlLeft.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); + GridData gd_scrlLeft = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1); + gd_scrlLeft.heightHint = 16; + gd_scrlLeft.widthHint = 16; + scrlLeft.setLayoutData(gd_scrlLeft); + scrlLeft.addPaintListener(paintEvent -> { + GC gc = paintEvent.gc; + gc.setBackground(buttonColor); + gc.setForeground(buttonColor); + int left = paintEvent.x+4; + int top = paintEvent.y+5; + int width=paintEvent.width-11; + int height= paintEvent.height-10; + int[] triangle = new int[] { + left, top+height/2, + left+width, top, + left+width, top+height}; + gc.fillPolygon( triangle ); + gc.drawPolygon( triangle ); + }); + scrlLeft.addSelectionListener(new SelectionAdapter() { + public void widgetSelected (SelectionEvent e){ + slider.setSelection(slider.getSelection()-10); + } + }); + scrlLeft.redraw(); + + slider = new Slider(this, SWT.NONE); + slider.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); + GridData gd_canvas = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); + gd_canvas.heightHint = 16; + slider.setLayoutData(gd_canvas); + + Button scrlRight = new Button(this, /*SWT.BORDER |*/ SWT.FLAT | SWT.CENTER); + scrlRight.setAlignment(SWT.CENTER); + GridData gd_scrlRight = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_scrlRight.heightHint = 16; + gd_scrlRight.widthHint = 16; + scrlRight.setLayoutData(gd_scrlRight); + scrlRight.addPaintListener(paintEvent -> { + GC gc = paintEvent.gc; + gc.setBackground(buttonColor); + gc.setForeground(buttonColor); + int left = paintEvent.x+6; + int top = paintEvent.y+5; + int width=paintEvent.width-11; + int height= paintEvent.height-10; + int[] triangle = new int[] { + left, top, + left+width, top+height/2, + left, top+height}; + gc.fillPolygon( triangle ); + gc.drawPolygon( triangle ); + }); + scrlRight.addSelectionListener(new SelectionAdapter() { + public void widgetSelected (SelectionEvent e){ + slider.setSelection(slider.getSelection()+10); + } + }); + redraw(); + } +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 5742af5..bbd9525 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -54,6 +54,7 @@ import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; @@ -61,6 +62,7 @@ import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; @@ -69,6 +71,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Slider; import org.eclipse.swt.widgets.Widget; import org.eclipse.wb.swt.SWTResourceManager; @@ -91,6 +94,7 @@ import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; +import com.minres.scviewer.database.ui.swt.sb.FlatScrollBar; public class WaveformView implements IWaveformView { @@ -330,8 +334,22 @@ public class WaveformView implements IWaveformView { rightSash.setBackground(SWTResourceManager.getColor(SWT.COLOR_GRAY)); Composite valuePane = new Composite(rightSash, SWT.NONE); - waveformCanvas = new WaveformCanvas(rightSash, SWT.NONE, styleProvider); - + + Composite waveformPane = new Composite(rightSash, SWT.NONE); + GridLayout gl_waveformPane = new GridLayout(1, false); + gl_waveformPane.verticalSpacing = 0; + gl_waveformPane.marginWidth = 0; + gl_waveformPane.marginHeight = 0; + waveformPane.setLayout(gl_waveformPane); + + waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider); + waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); + + Composite timeSliderPane = new WaveformSlider(waveformPane, SWT.NONE); + GridData gd_timeSlider = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); + gd_timeSlider.heightHint = 18; + timeSliderPane.setLayoutData(gd_timeSlider); + // create the name pane createTextPane(namePane, "Name"); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java new file mode 100644 index 0000000..96445f1 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java @@ -0,0 +1,108 @@ +package com.minres.scviewer.database.ui.swt.internal; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.layout.GridData; +import org.eclipse.wb.swt.ResourceManager; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.widgets.Slider; +import org.eclipse.wb.swt.SWTResourceManager; +import org.eclipse.swt.widgets.Scale; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.layout.FillLayout; + +public class ZoomingScrollbar extends Composite { + + /** + * Create the composite. + * @param parent + * @param style + */ + public ZoomingScrollbar(Composite parent, int style) { + super(parent, SWT.BORDER | SWT.NO_FOCUS); + GridLayout gridLayout = new GridLayout(3, false); + gridLayout.horizontalSpacing = 0; + gridLayout.verticalSpacing = 0; + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + setLayout(gridLayout); + + Button scrlLeft = new Button(this, SWT.BORDER | SWT.FLAT | SWT.CENTER); + scrlLeft.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); + GridData gd_scrlLeft = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1); + gd_scrlLeft.heightHint = 16; + gd_scrlLeft.widthHint = 16; + scrlLeft.setLayoutData(gd_scrlLeft); + + Slider slider = new Slider(this, SWT.NONE); + slider.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); + GridData gd_canvas = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); + gd_canvas.heightHint = 16; + slider.setLayoutData(gd_canvas); + + Button scrlRight = new Button(this, SWT.BORDER | SWT.FLAT | SWT.CENTER); + scrlRight.setAlignment(SWT.CENTER); + GridData gd_scrlRight = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_scrlRight.heightHint = 16; + gd_scrlRight.widthHint = 16; + scrlRight.setLayoutData(gd_scrlRight); + + SashForm sashForm = new SashForm(this, SWT.NONE); + sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); + + Composite composite = new Composite(sashForm, SWT.NONE); + composite.setBackground(SWTResourceManager.getColor(SWT.COLOR_MAGENTA)); + composite.setLayout(null); + + Composite wavformPane = new Composite(sashForm, SWT.BORDER | SWT.NO_FOCUS); + wavformPane.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE)); + GridLayout gl_wavformPane = new GridLayout(1, false); + gl_wavformPane.verticalSpacing = 0; + gl_wavformPane.marginWidth = 0; + gl_wavformPane.marginHeight = 0; + wavformPane.setLayout(gl_wavformPane); + + Composite waveformCanvas = new Composite(wavformPane, SWT.NONE); + waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); + + Composite timeSlider = new Composite(wavformPane, SWT.BORDER | SWT.NO_FOCUS); + GridLayout gl_timeSlider = new GridLayout(3, false); + gl_timeSlider.marginWidth = 0; + gl_timeSlider.verticalSpacing = 0; + gl_timeSlider.marginHeight = 0; + gl_timeSlider.horizontalSpacing = 0; + timeSlider.setLayout(gl_timeSlider); + GridData gd_timeSlider = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); + gd_timeSlider.heightHint = 16; + timeSlider.setLayoutData(gd_timeSlider); + + Button buttonLeft = new Button(timeSlider, SWT.BORDER | SWT.FLAT | SWT.CENTER); + buttonLeft.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); + GridData gd_buttonLeft = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1); + gd_buttonLeft.widthHint = 10; + gd_buttonLeft.heightHint = 16; + buttonLeft.setLayoutData(gd_buttonLeft); + + Slider slider2 = new Slider(timeSlider, SWT.NONE); + slider2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1)); + + Button buttonRight = new Button(timeSlider, SWT.FLAT | SWT.CENTER); + buttonRight.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); + GridData gd_buttonRight = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1); + gd_buttonRight.widthHint = 10; + gd_buttonRight.heightHint = 16; + buttonRight.setLayoutData(gd_buttonRight); + sashForm.setWeights(new int[] {1, 1}); + + } + + @Override + protected void checkSubclass() { + // Disable the check that prevents subclassing of SWT components + } +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ActionScheduler.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ActionScheduler.java new file mode 100644 index 0000000..8207914 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ActionScheduler.java @@ -0,0 +1,18 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.widgets.Display; + +public class ActionScheduler { + + private final Display display; + private final Runnable action; + + public ActionScheduler( Display display, Runnable action ) { + this.display = display; + this.action = action; + } + + public void schedule( int delay ) { + display.timerExec( delay, action ); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ButtonClick.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ButtonClick.java new file mode 100644 index 0000000..fe217a5 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ButtonClick.java @@ -0,0 +1,45 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; + +public class ButtonClick { + + public static final int LEFT_BUTTON = 1; + + private boolean armed; + + public boolean isArmed() { + return armed; + } + + public void arm( MouseEvent event ) { + if( event.button == LEFT_BUTTON ) { + armed = true; + } + } + + public void disarm() { + armed = false; + } + + public void trigger( MouseEvent event, Runnable action ) { + try { + doTrigger( event, action ); + } finally { + disarm(); + } + } + + private void doTrigger( MouseEvent event, Runnable action ) { + if( armed && inRange( event ) ) { + action.run(); + } + } + + private static boolean inRange( MouseEvent event ) { + Point size = ( ( Control )event.widget ).getSize(); + return event.x >= 0 && event.x <= size.x && event.y >= 0 && event.y <= size.y; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ClickControl.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ClickControl.java new file mode 100644 index 0000000..959d20e --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ClickControl.java @@ -0,0 +1,98 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + + +class ClickControl extends ControlAdapter implements ViewComponent, MouseDownActionTimer.TimerAction, MouseListener, MouseTrackListener { + + private final MouseDownActionTimer mouseDownActionTimer; + private final ClickAction clickAction; + private final ButtonClick buttonClick; + private final Label control; + private final ImageUpdate imageUpdate; + + public interface ClickAction extends Runnable { + void setCoordinates( int x, int y ); + } + + ClickControl( Composite parent, ClickAction clickAction, int maxExtension ) { + this.control = new Label( parent, SWT.NONE ); + this.imageUpdate = new ImageUpdate( control, maxExtension ); + this.buttonClick = new ButtonClick(); + this.mouseDownActionTimer = new MouseDownActionTimer( this, buttonClick, control.getDisplay() ); + this.clickAction = clickAction; + this.control.addMouseTrackListener( this ); + this.control.addMouseListener( this ); + this.control.addControlListener( this ); + } + + @Override + public void controlResized( ControlEvent event ) { + imageUpdate.update(); + } + + @Override + public Label getControl() { + return control; + } + + @Override + public void mouseDown( MouseEvent event ) { + buttonClick.arm( event ); + clickAction.setCoordinates( event.x, event.y ); + mouseDownActionTimer.activate(); + } + + @Override + public void mouseUp( MouseEvent event ) { + buttonClick.trigger( event, clickAction ); + } + + @Override + public void run() { + clickAction.run(); + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public void mouseExit( MouseEvent event ) { + buttonClick.disarm(); + } + + void setForeground( Color color ) { + imageUpdate.setForeground( color ); + } + + Color getForeground() { + return imageUpdate.getForeground(); + } + + void setBackground( Color color ) { + imageUpdate.setBackground( color ); + } + + Color getBackground() { + return imageUpdate.getBackground(); + } + + @Override + public void mouseEnter( MouseEvent event ) {} + + @Override + public void mouseHover( MouseEvent event ) {} + + @Override + public void mouseDoubleClick( MouseEvent event ) {} +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ComponentDistribution.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ComponentDistribution.java new file mode 100644 index 0000000..0111ee1 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ComponentDistribution.java @@ -0,0 +1,105 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static java.lang.Math.max; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +class ComponentDistribution { + + private static final int MIN_DRAG_LENGTH = 17; + + final int upFastLength; + final int dragStart; + final int dragLength; + final int downFastStart; + final int downFastLength; + final int downStart; + final int buttonLen; + + ComponentDistribution( int buttonLen, int len, int range, int pos, int thumb ) { + int slideLen = slideLen( buttonLen, len ); + int relDragLen = relDragLen( slideLen, range, thumb ); + int minDragLength = max( MIN_DRAG_LENGTH, buttonLen ); + int interval = interval( range, relDragLen, minDragLength ); + this.dragLength = dragLen( minDragLength, relDragLen ); + this.upFastLength = upFastLen( minDragLength, interval, pos, slideLen, relDragLen, dragLength ); + this.downStart = downStart( buttonLen, len ); + this.downFastStart = downFastStart( buttonLen, upFastLength, dragLength ); + this.dragStart = dragStart( buttonLen, upFastLength ); + this.downFastLength = downFastLen( minDragLength, interval, pos, slideLen, relDragLen, dragLength, upFastLength ); + this.buttonLen = buttonLen; + } + + private static int slideLen( int buttonLen, int len ) { + return len - buttonLen * 2; + } + + private static int relDragLen( int slideLen, int range, int thumb ) { + return divide( slideLen * thumb, range ); + } + + private static int interval( int range, int relDragLen, int minDragLength ) { + int result = range; + if( useMinDragLen( minDragLength, relDragLen ) ) { + result += minDragLength - relDragLen / 2; + } + return result; + } + + private static int dragLen( int buttonLen, int relDragLen ) { + return max( relDragLen, buttonLen ); + } + + private static int upFastLen( int buttonLen, int range, int pos, int slideLen, int relDragLen, int dragLen ) { + int result = slideLen * pos / range; + if( useMinDragLen( buttonLen, relDragLen ) ) { + result -= divide( ( dragLen - relDragLen ) * pos, range ); + } + return result; + } + + private static int downStart( int buttonLen, int len ) { + return len - buttonLen; + } + + private static int downFastStart( int buttonLen, int upFastLength, int dragLength ) { + return buttonLen + upFastLength + dragLength; + } + + private static int dragStart( int buttonLen, int upFastLen ) { + return buttonLen + upFastLen; + } + + private static int downFastLen( + int buttonLen, int range, int pos, int slideLen, int relDragLen, int dragLen, int upFastLen ) + { + int result = divide( slideLen * ( range - pos ), range ) - dragLen; + if( useMinDragLen( buttonLen, relDragLen ) ) { + result += divide( ( dragLen - relDragLen ) * pos, range ); + } + return adjustDownFastLen( result, slideLen, dragLen, upFastLen ); + } + + private static boolean useMinDragLen( int buttonLen, int relDragLen ) { + return relDragLen < buttonLen; + } + + static int divide( int dividend, int divisor ) { + BigDecimal bigDividend = new BigDecimal( dividend ); + BigDecimal bigDivisor = new BigDecimal( divisor ); + return bigDividend .divide( bigDivisor, 0, RoundingMode.HALF_EVEN ) .intValue(); + } + + private static int adjustDownFastLen( int tentative, int slideLen, int dragLen, int upFastLen ) { + // TODO [fappel]: Without this there is a flickering of the downFast label of one pixel. + // Check whether this can be resolved by better rounding or whatsoever. + int result = tentative; + if( slideLen < upFastLen + dragLen + result ) { + result--; + } else if( slideLen > upFastLen + dragLen + result ) { + result++; + } + return result; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Decrementer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Decrementer.java new file mode 100644 index 0000000..5627882 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Decrementer.java @@ -0,0 +1,24 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; + +import com.minres.scviewer.database.ui.swt.sb.ClickControl.ClickAction; + +class Decrementer implements ClickAction { + + private final FlatScrollBar scrollBar; + + Decrementer( FlatScrollBar scrollBar ) { + this.scrollBar = scrollBar; + } + + @Override + public void run() { + int selection = scrollBar.getSelection() - scrollBar.getIncrement(); + scrollBar.setSelectionInternal( selection, SWT.ARROW_UP ); + } + + @Override + public void setCoordinates( int x, int y ) { + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Direction.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Direction.java new file mode 100644 index 0000000..f2678ae --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Direction.java @@ -0,0 +1,203 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static com.minres.scviewer.database.ui.swt.sb.FlatScrollBar.BAR_BREADTH; +import static java.lang.Math.max; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +enum Direction { + + HORIZONTAL( SWT.HORIZONTAL ) { + + @Override + protected void layout( FlatScrollBar scrollBar, int buttonLength ) { + ComponentDistribution distribution = calculateComponentDistribution( scrollBar, buttonLength ); + Rectangle[] componentBounds = calculateComponentBounds( distribution, scrollBar ); + applyComponentBounds( scrollBar, componentBounds ); + } + + private ComponentDistribution calculateComponentDistribution( FlatScrollBar scrollBar, int buttonLength ) { + return calculateComponentDistribution( scrollBar, buttonLength, getControlBounds( scrollBar ).width ); + } + + private Rectangle[] calculateComponentBounds( ComponentDistribution distribution, FlatScrollBar scrollBar ) { + int width = getControlBounds( scrollBar ).width; + int height = getControlBounds( scrollBar ).height - FlatScrollBar.BAR_BREADTH + 1; + int balance = getRoundingBalance( distribution, scrollBar ); + return new Rectangle[] { + calcButtons( distribution, width, $( 0, CLEARANCE, distribution.buttonLen, height ) ), + $( distribution.buttonLen, CLEARANCE, distribution.upFastLength, height ), + calcDrag( distribution, $( distribution.dragStart, CLEARANCE, distribution.dragLength + balance, height ) ), + $( distribution.downFastStart, CLEARANCE, distribution.downFastLength - balance, height ), + calcButtons( distribution, width, $( distribution.downStart, CLEARANCE, distribution.buttonLen, height ) ) + }; + } + + private Rectangle calcButtons( ComponentDistribution distribution, int length, Rectangle bounds ) { + Rectangle result = bounds; + if( length <= distribution.buttonLen* 2 ) { + int downStart = calcDownStartForSmallLength( bounds.x, length ); + result = $( downStart, CLEARANCE, length / 2, bounds.height ); + } + return result; + } + + @Override + protected void setDefaultSize( Control control ) { + Point size = control.getSize(); + control.setSize( size.x, FlatScrollBar.BAR_BREADTH ); + } + + @Override + protected Point computeSize( Composite composite, int wHint, int hHint, boolean changed ) { + int x = wHint == SWT.DEFAULT ? composite.getParent().getClientArea().width : wHint; + return new Point( x, FlatScrollBar.BAR_BREADTH ); + } + + @Override + protected void expand( Control control, int maxExpansion ) { + Rectangle bounds = control.getBounds(); + int expand = expand( bounds.height, maxExpansion ); + control.setBounds( bounds.x, bounds.y - expand, bounds.width, bounds.height + expand ); + } + }, + + VERTICAL( SWT.VERTICAL ) { + + @Override + protected void layout( FlatScrollBar scrollBar, int buttonLength ) { + ComponentDistribution calculation = calculateComponentDistribution( scrollBar, buttonLength ); + applyComponentBounds( scrollBar, calculateComponentBounds( calculation, scrollBar ) ); + } + + private ComponentDistribution calculateComponentDistribution( FlatScrollBar scrollBar, int buttonLength ) { + return calculateComponentDistribution( scrollBar, buttonLength, getControlBounds( scrollBar ).height ); + } + + private Rectangle[] calculateComponentBounds( ComponentDistribution distribution, FlatScrollBar scrollBar ) { + int width = getControlBounds( scrollBar ).width - FlatScrollBar.BAR_BREADTH + 1; + int height = getControlBounds( scrollBar ).height; + int balance = getRoundingBalance( distribution, scrollBar ); + return new Rectangle[] { + calculateButtons( distribution, height, $( CLEARANCE, 0, width, distribution.buttonLen ) ), + $( CLEARANCE, distribution.buttonLen, width, distribution.upFastLength ), + calcDrag( distribution, $( CLEARANCE, distribution.dragStart, width, distribution.dragLength + balance ) ), + $( CLEARANCE, distribution.downFastStart, width, distribution.downFastLength - balance ), + calculateButtons( distribution, height, $( CLEARANCE, distribution.downStart, width, distribution.buttonLen ) ) + }; + } + + private Rectangle calculateButtons( ComponentDistribution distribution, int length, Rectangle bounds ) { + Rectangle result = bounds; + if( length <= distribution.buttonLen * 2 ) { + int downStart = calcDownStartForSmallLength( bounds.y, length ); + result = $( CLEARANCE, downStart, bounds.width, length / 2 ); + } + return result; + } + + @Override + protected void setDefaultSize( Control control ) { + Point size = control.getSize(); + control.setSize( FlatScrollBar.BAR_BREADTH, size.y ); + } + + @Override + protected Point computeSize( Composite composite, int wHint, int hHint, boolean changed ) { + int y = hHint == SWT.DEFAULT ? composite.getParent().getClientArea().height : hHint; + return new Point( FlatScrollBar.BAR_BREADTH, y ); + } + + @Override + protected void expand( Control control, int maxExpansion ) { + Rectangle bounds = control.getBounds(); + int expand = expand( bounds.width, maxExpansion ); + control.setBounds( bounds.x - expand, bounds.y, bounds.width + expand, bounds.height ); + } + }; + + static final Rectangle EMPTY_RECTANGLE = $( 0, 0, 0, 0 ); + static final int CLEARANCE = BAR_BREADTH - 2; + + private final int value; + + protected abstract void layout( FlatScrollBar scrollBar, int buttonLength ); + protected abstract void setDefaultSize( Control control ); + protected abstract Point computeSize( Composite comp, int wHint, int hHint, boolean changed ); + protected abstract void expand( Control control, int maxExpansion ); + + Direction( int value ) { + this.value = value; + } + + public int value() { + return value; + } + + private static ComponentDistribution calculateComponentDistribution( + FlatScrollBar scrollBar , int buttonLength , int length ) + { + int range = scrollBar.getMaximum() - scrollBar.getMinimum(); + int position = scrollBar.getSelection() - scrollBar.getMinimum(); + int thumb = scrollBar.getThumb(); + return new ComponentDistribution( buttonLength, length, range, position, thumb ); + } + + private static Rectangle getControlBounds( FlatScrollBar scrollBar ) { + return scrollBar.getClientArea(); + } + + private static void applyComponentBounds( FlatScrollBar scrollBar, Rectangle[] bounds ) { + scrollBar.up.getControl().setBounds( bounds[ 0 ] ); + scrollBar.upFast.getControl().setBounds( bounds[ 1 ] ); + scrollBar.drag.getControl().setBounds( bounds[ 2 ] ); + scrollBar.downFast.getControl().setBounds( bounds[ 3 ] ); + scrollBar.down.getControl().setBounds( bounds[ 4 ] ); + } + + // TODO [fappel]: There is a 1 pixel rounding problem at the seam of drag/downFast with down. + // Seems to work but I would prefer a better solution if possible + private static int getRoundingBalance( ComponentDistribution calculation, FlatScrollBar scrollBar ) { + int result = 0; + int maximumSelection = scrollBar.getMaximum() - scrollBar.getThumb(); + if( scrollBar.getSelection() == maximumSelection && 0 != calculation.downFastLength ) { + result = 1; + } + return result; + } + + private static int expand( int toExpand, int maxExpansion ) { + return max( 0, FlatScrollBar.BAR_BREADTH + maxExpansion - max( FlatScrollBar.BAR_BREADTH, toExpand ) ); + } + + private static Rectangle calcDrag( ComponentDistribution distribution, Rectangle bounds ) { + Rectangle result = bounds; + if( isUndercutOfDragVisibility( distribution ) ) { + result = EMPTY_RECTANGLE; + } + return result; + } + + private static boolean isUndercutOfDragVisibility( ComponentDistribution distribution ) { + return distribution.dragLength + distribution.buttonLen >= distribution.downStart; + } + + private static int calcDownStartForSmallLength( int position, int length ) { + int result = position; + if( isDownStartPosition( position ) ) { + result = length / 2; + } + return result; + } + private static boolean isDownStartPosition( int position ) { + return position > 0 || position < 0; + } + + private static Rectangle $( int x, int y, int width, int height ) { + return new Rectangle( x, y , width , height ); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragControl.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragControl.java new file mode 100644 index 0000000..4ca38eb --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragControl.java @@ -0,0 +1,105 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.DragDetectEvent; +import org.eclipse.swt.events.DragDetectListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + + +class DragControl + extends ControlAdapter + implements ViewComponent, DragDetectListener, MouseListener, MouseMoveListener +{ + + private final DragDetector dragDetector; + private final ImageUpdate imageUpdate; + private final DragAction dragAction; + private final Label control; + + private Point startingPosition; + + public interface DragAction { + void start(); + void run( int startX, int startY, int currentX, int currentY ); + void end(); + } + + DragControl( Composite parent, DragAction dragAction, int maxExpansion ) { + this.control = new Label( parent, SWT.NONE ); + this.imageUpdate = new ImageUpdate( control, maxExpansion ); + this.dragDetector = new DragDetector( control, 0 ); + this.dragAction = dragAction; + initializeControl(); + } + + @Override + public Label getControl() { + return control; + } + + @Override + public void dragDetected( DragDetectEvent event ) { + if( startingPosition != null ) { + dragAction.run( startingPosition.x, startingPosition.y, event.x, event.y ); + } + dragDetector.dragHandled(); + } + + @Override + public void mouseDown( MouseEvent event ) { + startingPosition = new Point( event.x, event.y ); + dragAction.start(); + } + + @Override + public void mouseUp( MouseEvent event ) { + if( startingPosition != null ) { + dragAction.end(); + } + startingPosition = null; + } + + @Override + public void mouseMove( MouseEvent event ) { + dragDetector.mouseMove( event ); + } + + @Override + public void controlResized( ControlEvent event ) { + imageUpdate.update(); + } + + void setForeground( Color color ) { + imageUpdate.setForeground( color ); + } + + Color getForeground() { + return imageUpdate.getForeground(); + } + + Color getBackground() { + return imageUpdate.getBackground(); + } + + void setBackground( Color color ) { + imageUpdate.setBackground( color ); + } + + private void initializeControl( ) { + control.addMouseListener( this ); + control.addMouseMoveListener( this ); + control.addControlListener( this ); + control.addDragDetectListener( this ); + } + + @Override + public void mouseDoubleClick( MouseEvent event ) {} +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragDetector.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragDetector.java new file mode 100644 index 0000000..b3e33a6 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragDetector.java @@ -0,0 +1,60 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; + +// TODO [fappel]: This is a workaround for a problem described here: +// http://stackoverflow.com/questions/3908290/mousedown-events-are-not-delivered-until-mouseup-when-a-drag-source-is-present +// This seems to be related to https://bugs.eclipse.org/bugs/show_bug.cgi?id=328396 +// which is resolved. As it did not work on my setup I adapted the workaround of the last +// stackoverflow answer. + +public class DragDetector { + + int lastMouseX; + int lastMouseY; + boolean dragEventGenerated; + + private final Control control; + private final int sensibility; + + public DragDetector( Control control, int sensibility ) { + this.control = control; + this.sensibility = sensibility; + this.control.setDragDetect( false ); + } + + public void mouseMove( MouseEvent e ) { + if( ( e.stateMask & SWT.BUTTON1 ) > 0 ) { + int deltaX = lastMouseX - e.x; + int deltaY = lastMouseY - e.y; + int dragDistance = deltaX * deltaX + deltaY * deltaY; + if( !dragEventGenerated && dragDistance > sensibility ) { + dragEventGenerated = true; + Event event = createDragEvent( e ); + control.notifyListeners( SWT.DragDetect, event ); + } + lastMouseX = e.x; + lastMouseY = e.y; + } + } + + public void dragHandled() { + dragEventGenerated = false; + } + + private Event createDragEvent( MouseEvent e ) { + Event event = new Event(); + event.type = SWT.DragDetect; + event.display = control.getDisplay(); + event.widget = control; + event.button = e.button; + event.stateMask = e.stateMask; + event.time = e.time; + event.x = e.x; + event.y = e.y; + return event; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragShifter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragShifter.java new file mode 100644 index 0000000..289223d --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/DragShifter.java @@ -0,0 +1,59 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static com.minres.scviewer.database.ui.swt.sb.Direction.HORIZONTAL; +import static com.minres.scviewer.database.ui.swt.sb.ShiftData.calculateSelectionRange; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; + +import com.minres.scviewer.database.ui.swt.sb.DragControl.DragAction; + +final class DragShifter implements DragAction { + + private final FlatScrollBar scrollBar; + private final int buttonLength; + + public DragShifter( FlatScrollBar scrollBar, int buttonLength ) { + this.scrollBar = scrollBar; + this.buttonLength = buttonLength; + } + + @Override + public void start() { + scrollBar.notifyListeners( SWT.DRAG ); + } + + @Override + public void run( int startX, int startY, int currentX, int currentY ) { + ShiftData shiftData = newShiftData( startX, startY, currentX, currentY ); + if( shiftData.canShift() ) { + int selectionRange = calculateSelectionRange( scrollBar ); + int selectionDelta = shiftData.calculateSelectionDelta( selectionRange ); + int selection = scrollBar.getSelection() + selectionDelta; + scrollBar.setSelectionInternal( selection, SWT.DRAG ); + } + } + + @Override + public void end() { + scrollBar.notifyListeners( SWT.NONE ); + } + + private ShiftData newShiftData( int startX, int startY, int currentX, int currentY ) { + ShiftData result; + if( scrollBar.direction == HORIZONTAL ) { + result = new ShiftData( buttonLength, getScrollBarSize().x, getDragSize().x, currentX - startX ); + } else { + result = new ShiftData( buttonLength, getScrollBarSize().y, getDragSize().y, currentY - startY ); + } + return result; + } + + private Point getScrollBarSize() { + return scrollBar.getSize(); + } + + private Point getDragSize() { + return scrollBar.drag.getControl().getSize(); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastDecrementer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastDecrementer.java new file mode 100644 index 0000000..744f522 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastDecrementer.java @@ -0,0 +1,49 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; + +import com.minres.scviewer.database.ui.swt.sb.ClickControl.ClickAction; + +class FastDecrementer implements ClickAction { + + private final FlatScrollBar scrollBar; + + private int x; + private int y; + + FastDecrementer( FlatScrollBar scrollBar ) { + this.scrollBar = scrollBar; + } + + @Override + public void run() { + Rectangle drag = getDragBounds(); + Point mouse = getMouseLocation(); + if( mouse.x <= drag.x || mouse.y <= drag.y ) { + int selection = scrollBar.getSelection() - scrollBar.getPageIncrement(); + scrollBar.setSelectionInternal( selection, SWT.PAGE_UP ); + } + } + + @Override + public void setCoordinates( int x, int y ) { + this.x = x; + this.y = y; + } + + private Point getMouseLocation() { + return getDisplay().map( scrollBar.upFast.getControl(), null, x, y ); + } + + private Rectangle getDragBounds() { + Rectangle dragBounds = scrollBar.drag.getControl().getBounds(); + return getDisplay().map( scrollBar, null, dragBounds ); + } + + private Display getDisplay() { + return scrollBar.getDisplay(); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastIncrementer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastIncrementer.java new file mode 100644 index 0000000..5ce4181 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FastIncrementer.java @@ -0,0 +1,42 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; + +import com.minres.scviewer.database.ui.swt.sb.ClickControl.ClickAction; + +class FastIncrementer implements ClickAction { + + private final FlatScrollBar scrollBar; + + private Point mouse; + + FastIncrementer( FlatScrollBar scrollBar ) { + this.scrollBar = scrollBar; + } + + @Override + public void run() { + Rectangle drag = getDragBounds(); + if( mouse.x > drag.x + drag.width || mouse.y > drag.y + drag.height ) { + int selection = scrollBar.getSelection() + scrollBar.getPageIncrement(); + scrollBar.setSelectionInternal( selection, SWT.PAGE_DOWN ); + } + } + + @Override + public void setCoordinates( int x, int y ) { + mouse = getMouseLocation( x, y ); + } + + private Point getMouseLocation(int x, int y) { + return Display.getCurrent().map( scrollBar.downFast.getControl(), null, x, y ); + } + + private Rectangle getDragBounds() { + Rectangle dragBounds = scrollBar.drag.getControl().getBounds(); + return Display.getCurrent().map( scrollBar, null, dragBounds ); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBar.java new file mode 100644 index 0000000..802d86a --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBar.java @@ -0,0 +1,295 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static com.minres.scviewer.database.ui.swt.sb.UntypedSelectionAdapter.lookup; + +import java.util.Collection; +import java.util.HashSet; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Listener; + +public class FlatScrollBar extends Composite { + + public static final int BAR_BREADTH = 6; + + static final int DEFAULT_MINIMUM = 0; + static final int DEFAULT_MAXIMUM = 100; + static final int DEFAULT_INCREMENT = 1; + static final int DEFAULT_THUMB = 10; + static final int DEFAULT_PAGE_INCREMENT = DEFAULT_THUMB; + static final int DEFAULT_SELECTION = 0; + static final int DEFAULT_BUTTON_LENGTH = 0; + static final int DEFAULT_MAX_EXPANSION = Direction.CLEARANCE + 2; + + final ClickControl up; + final ClickControl upFast; + final DragControl drag; + final ClickControl downFast; + final ClickControl down; + final Direction direction; + final MouseWheelShifter mouseWheelHandler; + final Collection listeners; + + private int minimum; + private int maximum; + private int increment; + private int pageIncrement; + private int thumb; + private int selection; + private boolean onDrag; + private int buttonLength; + + public FlatScrollBar( final Composite parent, int style ) { + this( parent, style, DEFAULT_BUTTON_LENGTH, DEFAULT_MAX_EXPANSION ); + } + + FlatScrollBar( Composite parent, int style, int buttonLength, int maxExpansion ) { + super( parent, SWT.NONE ); + super.setLayout( new FlatScrollBarLayout( getDirection( style ) ) ); + this.minimum = DEFAULT_MINIMUM; + this.maximum = DEFAULT_MAXIMUM; + this.increment = DEFAULT_INCREMENT; + this.pageIncrement = DEFAULT_PAGE_INCREMENT; + this.thumb = DEFAULT_THUMB; + this.selection = DEFAULT_SELECTION; + this.buttonLength = buttonLength; + this.direction = getDirection( style ); + this.direction.setDefaultSize( this ); + this.up = new ClickControl( this, new Decrementer( this ), maxExpansion ); + this.upFast = new ClickControl( this, new FastDecrementer( this ), maxExpansion ); + this.drag = new DragControl( this, new DragShifter( this, buttonLength ), maxExpansion ); + this.downFast = new ClickControl( this, new FastIncrementer( this ), maxExpansion ); + this.down = new ClickControl( this, new Incrementer( this ), maxExpansion ); + this.mouseWheelHandler = new MouseWheelShifter( this, parent, buttonLength ); + this.listeners = new HashSet(); + addMouseTrackListener( new MouseTracker( this, maxExpansion ) ); + addControlListener( new ResizeObserver( this ) ); + setDefaultColorScheme(); + } + + @Override + public void setLayout( Layout layout ) { + throw new UnsupportedOperationException( FlatScrollBar.class.getName() + " does not allow to change layout." ); + }; + + @Override + public int getStyle() { + return direction != null ? super.getStyle() | direction.value() : super.getStyle(); + }; + + Direction getDirection() { + return direction; + } + + public void setMinimum( int minimum ) { + if( this.minimum != minimum && minimum >= 0 && minimum < maximum ) { + this.minimum = minimum; + adjustThumb(); + adjustSelection(); + layout(); + } + } + + public int getMinimum() { + return minimum; + } + + public void setMaximum( int maximum ) { + if( this.maximum != maximum && maximum >= 0 && maximum > minimum ) { + this.maximum = maximum; + adjustThumb(); + adjustSelection(); + layout(); + } + } + + public int getMaximum() { + return maximum; + } + + public void setThumb( int thumb ) { + if( this.thumb != thumb && thumb >= 1 ) { + this.thumb = thumb; + adjustThumb(); + adjustSelection(); + layout(); + } + } + + public int getThumb() { + return thumb; + } + + public void setIncrement( int increment ) { + if( this.increment != increment ) { + this.increment = increment; + layout(); + } + } + + public int getIncrement() { + return increment; + } + + public void setPageIncrement( int pageIncrement ) { + this.pageIncrement = pageIncrement; + } + + public int getPageIncrement() { + return pageIncrement; + } + + public void setSelection( int selection ) { + if( !onDrag ) { + updateSelection( selection ); + } + } + + public int getSelection() { + return selection; + } + + public void addSelectionListener( SelectionListener selectionListener ) { + listeners.add( selectionListener ); + } + + public void removeSelectionListener( SelectionListener selectionListener ) { + listeners.remove( selectionListener ); + } + + @Override + public void addListener( int eventType, final Listener listener ) { + if( eventType == SWT.Selection ) { + addSelectionListener( new UntypedSelectionAdapter( listener ) ); + } else { + super.addListener( eventType, listener ); + } + } + + @Override + public void removeListener( int eventType, Listener listener ) { + if( eventType == SWT.Selection ) { + removeSelectionListener( lookup( listeners, listener ) ); + } else { + super.removeListener( eventType, listener ); + } + } + + @Override + public void layout() { + direction.layout( this, buttonLength ); + update(); + } + + public void setIncrementButtonLength( int length ) { + this.buttonLength = length; + layout(); + } + + public int getIncrementButtonLength() { + return buttonLength; + } + + public void setIncrementColor( Color color ) { + up.setForeground( color ); + down.setForeground( color ); + } + + public Color getIncrementColor() { + return up.getForeground(); + } + + public void setPageIncrementColor( Color color ) { + upFast.setForeground( color ); + downFast.setForeground( color ); + } + + public Color getPageIncrementColor() { + return upFast.getForeground(); + } + + public void setThumbColor( Color color ) { + drag.setForeground( color ); + } + + public Color getThumbColor() { + return drag.getForeground(); + } + + @Override + public void setBackground( Color color ) { + up.setBackground( color ); + upFast.setBackground( color ); + drag.setBackground( color ); + downFast.setBackground( color ); + down.setBackground( color ); + super.setBackground( color ); + } + + protected void setSelectionInternal( int selection, int detail ) { + int oldSelection = this.selection; + updateSelection( selection ); + if( oldSelection != this.selection ) { + notifyListeners( detail ); + } + } + + private void updateSelection( int selection ) { + if( this.selection != selection ) { + this.selection = selection; + adjustSelection(); + layout(); + } + } + + public void notifyListeners( int detail ) { + updateOnDrag( detail ); + SelectionEvent selectionEvent = createEvent( detail ); + for( SelectionListener listener : listeners ) { + listener.widgetSelected( selectionEvent ); + } + } + + private void updateOnDrag( int detail ) { + onDrag = ( onDrag || ( SWT.DRAG & detail ) > 0 ) && ( SWT.NONE != detail ); + } + + private SelectionEvent createEvent( int detail ) { + Event event = new Event(); + event.widget = this; + event.detail = detail; + return new SelectionEvent( event ); + } + + private void adjustThumb() { + if( thumb > maximum - minimum ) { + thumb = Math.min( maximum - minimum, thumb ); + thumb = Math.max( 1, thumb ); + } + } + + private void adjustSelection() { + selection = Math.min( selection, maximum - thumb ); + selection = Math.max( selection, minimum ); + } + + private static Direction getDirection( int style ) { + return ( style & SWT.HORIZONTAL ) > 0 ? Direction.HORIZONTAL : Direction.VERTICAL; + } + + private void setDefaultColorScheme() { + up.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_NORMAL_SHADOW ) ); + upFast.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND ) ); + drag.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND ) ); + downFast.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND ) ); + down.setForeground( Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_NORMAL_SHADOW ) ); + setBackground( getBackground() ); + } +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBarLayout.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBarLayout.java new file mode 100644 index 0000000..b8106bb --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/FlatScrollBarLayout.java @@ -0,0 +1,23 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Layout; + +class FlatScrollBarLayout extends Layout { + + private final Direction direction; + + public FlatScrollBarLayout( Direction orientation ) { + this.direction = orientation; + } + + @Override + protected void layout( Composite composite, boolean flushCache ) { + } + + @Override + protected Point computeSize( Composite composite, int wHint, int hHint, boolean flushCache ) { + return direction.computeSize( composite, wHint, hHint, flushCache ); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageDrawer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageDrawer.java new file mode 100644 index 0000000..8fb7495 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageDrawer.java @@ -0,0 +1,109 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static java.lang.Math.min; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; + +class ImageDrawer { + + static final String IMAGE_DRAWER_IS_DISPOSED = "ImageDrawer is disposed."; + + private final int maxExpansion; + + private Color background; + private Color foreground; + + ImageDrawer( int expansion ) { + this( expansion, getSystemColor( SWT.COLOR_WIDGET_DARK_SHADOW ), getSystemColor( SWT.COLOR_LIST_BACKGROUND ) ); + } + + ImageDrawer( int expansion, Color background, Color foreground ) { + this.maxExpansion = expansion; + this.foreground = defensiveCopy( background ); + this.background = defensiveCopy( foreground ); + } + + void setForeground( Color foreground ) { + checkDisposed(); + if( foreground != null ) { + this.foreground = prepareColorAttribute( this.foreground, foreground ); + } + } + + Color getForeground() { + checkDisposed(); + return foreground; + } + + void setBackground( Color background ) { + checkDisposed(); + if( background != null ) { + this.background = prepareColorAttribute( this.background, background ); + } + } + + Color getBackground() { + checkDisposed(); + return background; + } + + Image draw( int width, int height ) { + checkDisposed(); + Image result = new Image( getDisplay(), width, height ); + GC gc = new GC( result ); + try { + draw( gc, width, height ); + } finally { + gc.dispose(); + } + return result; + } + + boolean isDisposed() { + return background.isDisposed(); + } + + void dispose() { + if( !isDisposed() ) { + this.background.dispose(); + this.foreground.dispose(); + } + } + + private void draw( GC gc, int width, int height ) { + gc.setBackground( background ); + gc.fillRectangle( 0, 0, width, height ); + gc.setBackground( foreground ); + gc.setAdvanced( true ); + gc.setAntialias( SWT.ON ); + int arc = min( width, height ) == 1 ? 1 : maxExpansion + 2; + gc.fillRoundRectangle( 0, 0, width, height, arc, arc ); + } + + private void checkDisposed() { + if( isDisposed() ) { + throw new IllegalStateException( IMAGE_DRAWER_IS_DISPOSED ); + } + } + + private static Color getSystemColor( int colorCode ) { + return getDisplay().getSystemColor( colorCode ); + } + + private static Color prepareColorAttribute( Color oldColor, Color newColor ) { + oldColor.dispose(); + return defensiveCopy( newColor ); + } + + private static Color defensiveCopy( Color background ) { + return new Color( getDisplay(), background.getRGB() ); + } + + private static Display getDisplay() { + return Display.getCurrent(); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageUpdate.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageUpdate.java new file mode 100644 index 0000000..73719a9 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ImageUpdate.java @@ -0,0 +1,46 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Label; + +class ImageUpdate { + + private final ImageDrawer imageDrawer; + private final Label control; + + ImageUpdate( Label control, int maxExpansion ) { + this.imageDrawer = new ImageDrawer( maxExpansion ); + this.control = control; + this.control.addListener( SWT.Dispose, evt -> imageDrawer.dispose() ); + } + + void setForeground( Color color ) { + imageDrawer.setForeground( color ); + } + + Color getForeground() { + return imageDrawer.getForeground(); + } + + void setBackground( Color color ) { + imageDrawer.setBackground( color ); + } + + Color getBackground() { + return imageDrawer.getBackground(); + } + + void update() { + if( !control.isDisposed() ) { + if( control.getImage() != null ) { + control.getImage().dispose(); + } + Point size = control.getSize(); + if( size.x > 0 && size.y > 0 ) { + control.setImage( imageDrawer.draw( size.x, size.y ) ); + } + } + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Incrementer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Incrementer.java new file mode 100644 index 0000000..351e058 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/Incrementer.java @@ -0,0 +1,24 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.SWT; + +import com.minres.scviewer.database.ui.swt.sb.ClickControl.ClickAction; + +class Incrementer implements ClickAction { + + private final FlatScrollBar scrollBar; + + Incrementer( FlatScrollBar scrollBar ) { + this.scrollBar = scrollBar; + } + + @Override + public void run() { + int selection = scrollBar.getSelection() + scrollBar.getIncrement(); + scrollBar.setSelectionInternal( selection, SWT.ARROW_DOWN ); + } + + @Override + public void setCoordinates( int x, int y ) { + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseDownActionTimer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseDownActionTimer.java new file mode 100644 index 0000000..1de6295 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseDownActionTimer.java @@ -0,0 +1,37 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.widgets.Display; + +public class MouseDownActionTimer implements Runnable { + + public static final int INITIAL_DELAY = 300; + public static final int FAST_DELAY = 50; + + private final ActionScheduler scheduler; + private final TimerAction timerAction; + private final ButtonClick mouseClick; + + public interface TimerAction extends Runnable { + boolean isEnabled(); + } + + public MouseDownActionTimer( TimerAction timerAction, ButtonClick mouseClick, Display display ) { + this.scheduler = new ActionScheduler( display, this ); + this.timerAction = timerAction; + this.mouseClick = mouseClick; + } + + public void activate() { + if( timerAction.isEnabled() ) { + scheduler.schedule( INITIAL_DELAY ); + } + } + + @Override + public void run() { + if( mouseClick.isArmed() && timerAction.isEnabled() ) { + timerAction.run(); + scheduler.schedule( FAST_DELAY ); + } + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseTracker.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseTracker.java new file mode 100644 index 0000000..f36e825 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseTracker.java @@ -0,0 +1,66 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; + +class MouseTracker extends MouseTrackAdapter implements Runnable, DisposeListener { + + static final int DELAY = 500; + + private final FlatScrollBar scrollBar; + private final int maxExpansion; + + private Rectangle expandedBounds; + private Rectangle originBounds; + private boolean mouseOver; + private boolean disposed; + + MouseTracker( FlatScrollBar scrollBar, int maxExpansion ) { + this.scrollBar = scrollBar; + this.maxExpansion = maxExpansion; + this.scrollBar.addDisposeListener( this ); + this.scrollBar.up.getControl().addMouseTrackListener( this ); + this.scrollBar.upFast.getControl().addMouseTrackListener( this ); + this.scrollBar.drag.getControl().addMouseTrackListener( this ); + this.scrollBar.downFast.getControl().addMouseTrackListener( this ); + this.scrollBar.down.getControl().addMouseTrackListener( this ); + } + + @Override + public void mouseEnter( MouseEvent event ) { + mouseOver = true; + if( !disposed && originBounds == null ) { + originBounds = scrollBar.getBounds(); + scrollBar.getDirection().expand( scrollBar, maxExpansion ); + expandedBounds = scrollBar.getBounds(); + } + } + + @Override + public void mouseExit( MouseEvent event ) { + mouseOver = false; + if( !disposed ) { + Display.getCurrent().timerExec( DELAY, this ); + } + } + + @Override + public void run() { + if( !disposed && !mouseOver ) { + if( scrollBar.getBounds().equals( expandedBounds ) ) { + scrollBar.setBounds( originBounds ); + } + originBounds = null; + expandedBounds = null; + } + } + + @Override + public void widgetDisposed( DisposeEvent e ) { + disposed = true; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseWheelShifter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseWheelShifter.java new file mode 100644 index 0000000..4baa1be --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/MouseWheelShifter.java @@ -0,0 +1,69 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static com.minres.scviewer.database.ui.swt.sb.Direction.HORIZONTAL; +import static com.minres.scviewer.database.ui.swt.sb.ShiftData.calculateSelectionRange; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; + +public class MouseWheelShifter implements Listener, DisposeListener { + + private final FlatScrollBar scrollBar; + private final Composite parent; + private final int buttonLength; + + MouseWheelShifter( FlatScrollBar scrollBar, Composite parent, int buttonLength ) { + this.scrollBar = scrollBar; + this.parent = parent; + this.buttonLength = buttonLength; + parent.addListener( getListenerType(), this ); + scrollBar.addDisposeListener( this ); + } + + @Override + public void handleEvent( Event event ) { + handleMouseWheelScroll( event ); + } + + @Override + public void widgetDisposed( DisposeEvent e ) { + parent.removeListener( getListenerType(), this ); + } + + private void handleMouseWheelScroll( Event event ) { + ShiftData shiftData = newShiftData( event.count ); + if( shiftData.canShift() ) { + int selectionRange = calculateSelectionRange( scrollBar ); + int selectionDelta = shiftData.calculateSelectionDelta( selectionRange ); + int selection = scrollBar.getSelection() - selectionDelta; + scrollBar.setSelectionInternal( selection, scrollBar.direction.value() ); + } + } + + private ShiftData newShiftData( int delta ) { + ShiftData result; + if( scrollBar.direction == Direction.HORIZONTAL ) { + result = new ShiftData( buttonLength, getScrollBarSize().x, getDragSize().x, delta ); + } else { + result = new ShiftData( buttonLength, getScrollBarSize().y, getDragSize().y, delta ); + } + return result; + } + + private Point getScrollBarSize() { + return scrollBar.getSize(); + } + + private Point getDragSize() { + return scrollBar.drag.getControl().getSize(); + } + + private int getListenerType() { + return scrollBar.direction == HORIZONTAL ? SWT.MouseHorizontalWheel: SWT.MouseVerticalWheel; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ResizeObserver.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ResizeObserver.java new file mode 100644 index 0000000..20cb2b3 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ResizeObserver.java @@ -0,0 +1,19 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; + +class ResizeObserver extends ControlAdapter { + + private final FlatScrollBar flatScrollBar; + + public ResizeObserver( FlatScrollBar flatScrollBar ) { + this.flatScrollBar = flatScrollBar; + } + + @Override + public void controlResized( ControlEvent event ) { + flatScrollBar.layout(); + flatScrollBar.moveAbove( null ); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ShiftData.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ShiftData.java new file mode 100644 index 0000000..0bdeccd --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ShiftData.java @@ -0,0 +1,32 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import static com.minres.scviewer.database.ui.swt.sb.ComponentDistribution.divide; + +class ShiftData { + + private final int slidePixels; + private final int movedPixels; + private final int buttonLength; + + ShiftData( int buttonLength, int scrollBarPixels, int dragPixels, int movedPixels ) { + this.buttonLength = buttonLength; + this.slidePixels = calculateSlidePixels( scrollBarPixels, dragPixels ); + this.movedPixels = movedPixels; + } + + boolean canShift( ) { + return slidePixels > 0; + } + + int calculateSelectionDelta( int selectionRange ) { + return divide( movedPixels * selectionRange, slidePixels ); + } + + static int calculateSelectionRange( FlatScrollBar scrollBar ) { + return scrollBar.getMaximum() - scrollBar.getMinimum() - scrollBar.getThumb(); + } + + private int calculateSlidePixels( int scrollBarPixels, int dragPixels ) { + return scrollBarPixels - 2 * buttonLength - dragPixels; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/UntypedSelectionAdapter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/UntypedSelectionAdapter.java new file mode 100644 index 0000000..d5fffd8 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/UntypedSelectionAdapter.java @@ -0,0 +1,43 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import java.util.Collection; + +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; + +class UntypedSelectionAdapter extends SelectionAdapter { + + final Listener listener; + + UntypedSelectionAdapter( Listener listener ) { + this.listener = listener; + } + + @Override + public void widgetSelected( SelectionEvent selectionEvent ) { + Event event = new Event(); + event.widget = selectionEvent.widget; + event.detail = selectionEvent.detail; + listener.handleEvent( event ); + } + + static SelectionListener lookup( Collection listeners, Listener untypedListener ) { + for( SelectionListener listener : listeners ) { + if( isAdapterType( listener ) && matches( untypedListener, listener ) ) { + return listener; + } + } + return null; + } + + private static boolean isAdapterType( SelectionListener listener ) { + return listener instanceof UntypedSelectionAdapter; + } + + private static boolean matches( Listener untypedListener, SelectionListener listener ) { + return ( ( UntypedSelectionAdapter )listener ).listener == untypedListener; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ViewComponent.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ViewComponent.java new file mode 100644 index 0000000..af1779c --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/sb/ViewComponent.java @@ -0,0 +1,7 @@ +package com.minres.scviewer.database.ui.swt.sb; + +import org.eclipse.swt.widgets.Control; + +public interface ViewComponent { + Control getControl(); +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/ResourceManager.java b/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/ResourceManager.java new file mode 100644 index 0000000..8e96dfe --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/ResourceManager.java @@ -0,0 +1,438 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. and others + * 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: + * Google, Inc. - initial API and implementation + * Wim Jongman - 1.8 and higher compliance + *******************************************************************************/ +package org.eclipse.wb.swt; + +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.CompositeImageDescriptor; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageDataProvider; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.osgi.framework.Bundle; + +/** + * Utility class for managing OS resources associated with SWT/JFace controls + * such as colors, fonts, images, etc. + * + * This class is created automatically when you fiddle around with images and + * colors in WB. You might want to prevent your application from using this + * class and provide your own more effective means of resource caching. + * + * Even though this class can be used to manage these resources, if they are + * here for the duration of the application and not used then you still have an + * effective resource leak. + * + * Application code must explicitly invoke the dispose() method to + * release the operating system resources managed by cached objects when those + * objects and OS resources are no longer needed. + * + * This class may be freely distributed as part of any application or plugin. + *

+ * + * @author scheglov_ke + * @author Dan Rubel + * @author Wim Jongman + */ +public class ResourceManager extends SWTResourceManager { + + /** + * The map where we store our images. + */ + private static Map m_descriptorImageMap = new HashMap(); + + /** + * Returns an {@link ImageDescriptor} stored in the file at the specified path + * relative to the specified class. + * + * @param clazz the {@link Class} relative to which to find the image + * descriptor. + * @param path the path to the image file. + * @return the {@link ImageDescriptor} stored in the file at the specified path. + */ + public static ImageDescriptor getImageDescriptor(Class clazz, String path) { + return ImageDescriptor.createFromFile(clazz, path); + } + + /** + * Returns an {@link ImageDescriptor} stored in the file at the specified path. + * + * @param path the path to the image file. + * @return the {@link ImageDescriptor} stored in the file at the specified path. + */ + public static ImageDescriptor getImageDescriptor(String path) { + try { + return ImageDescriptor.createFromURL(new File(path).toURI().toURL()); + } catch (MalformedURLException e) { + return null; + } + } + + /** + * Returns an {@link Image} based on the specified {@link ImageDescriptor}. + * + * @param descriptor the {@link ImageDescriptor} for the {@link Image}. + * @return the {@link Image} based on the specified {@link ImageDescriptor}. + */ + public static Image getImage(ImageDescriptor descriptor) { + if (descriptor == null) { + return null; + } + Image image = m_descriptorImageMap.get(descriptor); + if (image == null) { + image = descriptor.createImage(); + m_descriptorImageMap.put(descriptor, image); + } + return image; + } + + /** + * Maps images to decorated images. + */ + @SuppressWarnings("unchecked") + private static Map>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY]; + + /** + * Returns an {@link Image} composed of a base image decorated by another image. + * + * @param baseImage the base {@link Image} that should be decorated. + * @param decorator the {@link Image} to decorate the base image. + * @return {@link Image} The resulting decorated image. + */ + public static Image decorateImage(Image baseImage, Image decorator) { + return decorateImage(baseImage, decorator, BOTTOM_RIGHT); + } + + /** + * Returns an {@link Image} composed of a base image decorated by another image. + * + * @param baseImage + * the base {@link Image} that should be decorated. + * @param decorator + * the {@link Image} to decorate the base image. + * @param corner + * the corner to place decorator image. + * @return the resulting decorated {@link Image}. + */ + public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) { + if (corner <= 0 || corner >= LAST_CORNER_KEY) { + throw new IllegalArgumentException("Wrong decorate corner"); + } + Map> cornerDecoratedImageMap = m_decoratedImageMap[corner]; + if (cornerDecoratedImageMap == null) { + cornerDecoratedImageMap = new HashMap>(); + m_decoratedImageMap[corner] = cornerDecoratedImageMap; + } + Map decoratedMap = cornerDecoratedImageMap.get(baseImage); + if (decoratedMap == null) { + decoratedMap = new HashMap(); + cornerDecoratedImageMap.put(baseImage, decoratedMap); + } + // + Image result = decoratedMap.get(decorator); + if (result == null) { + final Rectangle bib = baseImage.getBounds(); + final Rectangle dib = decorator.getBounds(); + final Point baseImageSize = new Point(bib.width, bib.height); + CompositeImageDescriptor compositImageDesc = new CompositeImageDescriptor() { + @Override + protected void drawCompositeImage(int width, int height) { + drawImage(createCachedImageDataProvider(baseImage), 0, 0); + if (corner == TOP_LEFT) { + drawImage(getUnzoomedImageDataProvider(decorator.getImageData()) , 0, 0); + } else if (corner == TOP_RIGHT) { + drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), bib.width - dib.width, 0); + } else if (corner == BOTTOM_LEFT) { + drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), 0, bib.height - dib.height); + } else if (corner == BOTTOM_RIGHT) { + drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), bib.width - dib.width, bib.height - dib.height); + } + } + @Override + protected Point getSize() { + return baseImageSize; + } + }; + // + result = compositImageDesc.createImage(); + decoratedMap.put(decorator, result); + } + return result; + } + + private static ImageDataProvider getUnzoomedImageDataProvider(ImageData imageData) { + return zoom -> zoom == 100 ? imageData : null; + } + + + /** + * Dispose all of the cached images. + */ + public static void disposeImages() { + SWTResourceManager.disposeImages(); + // dispose ImageDescriptor images + { + for (Iterator I = m_descriptorImageMap.values().iterator(); I.hasNext();) { + I.next().dispose(); + } + m_descriptorImageMap.clear(); + } + // dispose decorated images + for (int i = 0; i < m_decoratedImageMap.length; i++) { + Map> cornerDecoratedImageMap = m_decoratedImageMap[i]; + if (cornerDecoratedImageMap != null) { + for (Map decoratedMap : cornerDecoratedImageMap.values()) { + for (Image image : decoratedMap.values()) { + image.dispose(); + } + decoratedMap.clear(); + } + cornerDecoratedImageMap.clear(); + } + } + // dispose plugin images + { + for (Iterator I = m_URLImageMap.values().iterator(); I.hasNext();) { + I.next().dispose(); + } + m_URLImageMap.clear(); + } + } + + //////////////////////////////////////////////////////////////////////////// + // + // Plugin images support + // + //////////////////////////////////////////////////////////////////////////// + /** + * Maps URL to images. + */ + private static Map m_URLImageMap = new HashMap(); + + /** + * Provider for plugin resources, used by WindowBuilder at design time. + */ + public interface PluginResourceProvider { + URL getEntry(String symbolicName, String path); + } + + /** + * Instance of {@link PluginResourceProvider}, used by WindowBuilder at design + * time. + */ + private static PluginResourceProvider m_designTimePluginResourceProvider = null; + + /** + * Returns an {@link Image} based on a plugin and file path. + * + * @param plugin the plugin {@link Object} containing the image + * @param name the path to the image within the plugin + * @return the {@link Image} stored in the file at the specified path + * + * @deprecated Use {@link #getPluginImage(String, String)} instead. + */ + @Deprecated + public static Image getPluginImage(Object plugin, String name) { + try { + URL url = getPluginImageURL(plugin, name); + if (url != null) { + return getPluginImageFromUrl(url); + } + } catch (Throwable e) { + // Ignore any exceptions + } + return null; + } + + /** + * Returns an {@link Image} based on a {@link Bundle} and resource entry path. + * + * @param symbolicName the symbolic name of the {@link Bundle}. + * @param path the path of the resource entry. + * @return the {@link Image} stored in the file at the specified path. + */ + public static Image getPluginImage(String symbolicName, String path) { + try { + URL url = getPluginImageURL(symbolicName, path); + if (url != null) { + return getPluginImageFromUrl(url); + } + } catch (Throwable e) { + // Ignore any exceptions + } + return null; + } + + /** + * Returns an {@link Image} based on given {@link URL}. + */ + private static Image getPluginImageFromUrl(URL url) { + try { + try { + String key = url.toExternalForm(); + Image image = m_URLImageMap.get(key); + if (image == null) { + InputStream stream = url.openStream(); + try { + image = getImage(stream); + m_URLImageMap.put(key, image); + } finally { + stream.close(); + } + } + return image; + } catch (Throwable e) { + // Ignore any exceptions + } + } catch (Throwable e) { + // Ignore any exceptions + } + return null; + } + + /** + * Returns an {@link ImageDescriptor} based on a plugin and file path. + * + * @param plugin the plugin {@link Object} containing the image. + * @param name the path to th eimage within the plugin. + * @return the {@link ImageDescriptor} stored in the file at the specified path. + * + * @deprecated Use {@link #getPluginImageDescriptor(String, String)} instead. + */ + @Deprecated + public static ImageDescriptor getPluginImageDescriptor(Object plugin, String name) { + try { + try { + URL url = getPluginImageURL(plugin, name); + return ImageDescriptor.createFromURL(url); + } catch (Throwable e) { + // Ignore any exceptions + } + } catch (Throwable e) { + // Ignore any exceptions + } + return null; + } + + /** + * Returns an {@link ImageDescriptor} based on a {@link Bundle} and resource + * entry path. + * + * @param symbolicName the symbolic name of the {@link Bundle}. + * @param path the path of the resource entry. + * @return the {@link ImageDescriptor} based on a {@link Bundle} and resource + * entry path. + */ + public static ImageDescriptor getPluginImageDescriptor(String symbolicName, String path) { + try { + URL url = getPluginImageURL(symbolicName, path); + if (url != null) { + return ImageDescriptor.createFromURL(url); + } + } catch (Throwable e) { + // Ignore any exceptions + } + return null; + } + + /** + * Returns an {@link URL} based on a {@link Bundle} and resource entry path. + */ + private static URL getPluginImageURL(String symbolicName, String path) { + // try runtime plugins + { + Bundle bundle = Platform.getBundle(symbolicName); + if (bundle != null) { + return bundle.getEntry(path); + } + } + // try design time provider + if (m_designTimePluginResourceProvider != null) { + return m_designTimePluginResourceProvider.getEntry(symbolicName, path); + } + // no such resource + return null; + } + + /** + * Returns an {@link URL} based on a plugin and file path. + * + * @param plugin the plugin {@link Object} containing the file path. + * @param name the file path. + * @return the {@link URL} representing the file at the specified path. + * @throws Exception + */ + private static URL getPluginImageURL(Object plugin, String name) throws Exception { + // try to work with 'plugin' as with OSGI BundleContext + try { + Class BundleClass = Class.forName("org.osgi.framework.Bundle"); //$NON-NLS-1$ + Class BundleContextClass = Class.forName("org.osgi.framework.BundleContext"); //$NON-NLS-1$ + if (BundleContextClass.isAssignableFrom(plugin.getClass())) { + Method getBundleMethod = BundleContextClass.getMethod("getBundle", new Class[0]); //$NON-NLS-1$ + Object bundle = getBundleMethod.invoke(plugin, new Object[0]); + // + Class PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$ + Constructor pathConstructor = PathClass.getConstructor(new Class[] { String.class }); + Object path = pathConstructor.newInstance(new Object[] { name }); + // + Class IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$ + Class PlatformClass = Class.forName("org.eclipse.core.runtime.Platform"); //$NON-NLS-1$ + Method findMethod = PlatformClass.getMethod("find", new Class[] { BundleClass, IPathClass }); //$NON-NLS-1$ + return (URL) findMethod.invoke(null, new Object[] { bundle, path }); + } + } catch (Throwable e) { + // Ignore any exceptions + } + // else work with 'plugin' as with usual Eclipse plugin + { + Class PluginClass = Class.forName("org.eclipse.core.runtime.Plugin"); //$NON-NLS-1$ + if (PluginClass.isAssignableFrom(plugin.getClass())) { + // + Class PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$ + Constructor pathConstructor = PathClass.getConstructor(new Class[] { String.class }); + Object path = pathConstructor.newInstance(new Object[] { name }); + // + Class IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$ + Method findMethod = PluginClass.getMethod("find", new Class[] { IPathClass }); //$NON-NLS-1$ + return (URL) findMethod.invoke(plugin, new Object[] { path }); + } + } + return null; + } + + //////////////////////////////////////////////////////////////////////////// + // + // General + // + //////////////////////////////////////////////////////////////////////////// + /** + * Dispose of cached objects and their underlying OS resources. This should only + * be called when the cached objects are no longer needed (e.g. on application + * shutdown). + */ + public static void dispose() { + disposeColors(); + disposeFonts(); + disposeImages(); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/SWTResourceManager.java b/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/SWTResourceManager.java index 0024a03..d8a2858 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/SWTResourceManager.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/SWTResourceManager.java @@ -29,17 +29,14 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Display; /** - * Utility class for managing OS resources associated with SWT controls such as - * colors, fonts, images, etc. + * Utility class for managing OS resources associated with SWT controls such as colors, fonts, images, etc. *

- * !!! IMPORTANT !!! Application code must explicitly invoke the - * dispose() method to release the operating system resources - * managed by cached objects when those objects and OS resources are no longer + * !!! IMPORTANT !!! Application code must explicitly invoke the dispose() method to release the + * operating system resources managed by cached objects when those objects and OS resources are no longer * needed (e.g. on application shutdown) *

* This class may be freely distributed as part of any application or plugin. *

- * * @author scheglov_ke * @author Dan Rubel */ @@ -49,54 +46,57 @@ public class SWTResourceManager { // Color // //////////////////////////////////////////////////////////////////////////// - private static Map colorMap = new HashMap<>(); - - private SWTResourceManager() {} - + private static Map m_colorMap = new HashMap(); /** * Returns the system {@link Color} matching the specific ID. * - * @param systemColorID the ID value for the color + * @param systemColorID + * the ID value for the color * @return the system {@link Color} matching the specific ID */ public static Color getColor(int systemColorID) { Display display = Display.getCurrent(); return display.getSystemColor(systemColorID); } - /** * Returns a {@link Color} given its red, green and blue component values. * - * @param r the red component of the color - * @param g the green component of the color - * @param b the blue component of the color - * @return the {@link Color} matching the given red, green and blue component - * values + * @param r + * the red component of the color + * @param g + * the green component of the color + * @param b + * the blue component of the color + * @return the {@link Color} matching the given red, green and blue component values */ public static Color getColor(int r, int g, int b) { return getColor(new RGB(r, g, b)); } - /** * Returns a {@link Color} given its RGB value. * - * @param rgb the {@link RGB} value of the color + * @param rgb + * the {@link RGB} value of the color * @return the {@link Color} matching the RGB value */ public static Color getColor(RGB rgb) { - return colorMap.computeIfAbsent(rgb, k -> new Color(Display.getCurrent(), rgb)); + Color color = m_colorMap.get(rgb); + if (color == null) { + Display display = Display.getCurrent(); + color = new Color(display, rgb); + m_colorMap.put(rgb, color); + } + return color; } - /** * Dispose of all the cached {@link Color}'s. */ public static void disposeColors() { - for (Color color : colorMap.values()) { + for (Color color : m_colorMap.values()) { color.dispose(); } - colorMap.clear(); + m_colorMap.clear(); } - //////////////////////////////////////////////////////////////////////////// // // Image @@ -105,12 +105,12 @@ public class SWTResourceManager { /** * Maps image paths to images. */ - private static Map imageMap = new HashMap<>(); - + private static Map m_imageMap = new HashMap(); /** * Returns an {@link Image} encoded by the specified {@link InputStream}. * - * @param stream the {@link InputStream} encoding the image data + * @param stream + * the {@link InputStream} encoding the image data * @return the {@link Image} encoded by the specified input stream */ protected static Image getImage(InputStream stream) throws IOException { @@ -125,55 +125,52 @@ public class SWTResourceManager { stream.close(); } } - /** * Returns an {@link Image} stored in the file at the specified path. * - * @param path the path to the image file + * @param path + * the path to the image file * @return the {@link Image} stored in the file at the specified path */ public static Image getImage(String path) { - Image image = imageMap.get(path); + Image image = m_imageMap.get(path); if (image == null) { try { image = getImage(new FileInputStream(path)); - imageMap.put(path, image); + m_imageMap.put(path, image); } catch (Exception e) { image = getMissingImage(); - imageMap.put(path, image); + m_imageMap.put(path, image); } } return image; } - /** - * Returns an {@link Image} stored in the file at the specified path relative to - * the specified class. + * Returns an {@link Image} stored in the file at the specified path relative to the specified class. * - * @param clazz the {@link Class} relative to which to find the image - * @param path the path to the image file, if starts with '/' + * @param clazz + * the {@link Class} relative to which to find the image + * @param path + * the path to the image file, if starts with '/' * @return the {@link Image} stored in the file at the specified path */ public static Image getImage(Class clazz, String path) { String key = clazz.getName() + '|' + path; - Image image = imageMap.get(key); + Image image = m_imageMap.get(key); if (image == null) { try { image = getImage(clazz.getResourceAsStream(path)); - imageMap.put(key, image); + m_imageMap.put(key, image); } catch (Exception e) { image = getMissingImage(); - imageMap.put(key, image); + m_imageMap.put(key, image); } } return image; } - private static final int MISSING_IMAGE_SIZE = 10; - /** - * @return the small {@link Image} that can be used as placeholder for missing - * image. + * @return the small {@link Image} that can be used as placeholder for missing image. */ private static Image getMissingImage() { Image image = new Image(Display.getCurrent(), MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE); @@ -185,7 +182,6 @@ public class SWTResourceManager { // return image; } - /** * Style constant for placing decorator image in top left corner of base image. */ @@ -195,13 +191,11 @@ public class SWTResourceManager { */ public static final int TOP_RIGHT = 2; /** - * Style constant for placing decorator image in bottom left corner of base - * image. + * Style constant for placing decorator image in bottom left corner of base image. */ public static final int BOTTOM_LEFT = 3; /** - * Style constant for placing decorator image in bottom right corner of base - * image. + * Style constant for placing decorator image in bottom right corner of base image. */ public static final int BOTTOM_RIGHT = 4; /** @@ -212,77 +206,83 @@ public class SWTResourceManager { * Maps images to decorated images. */ @SuppressWarnings("unchecked") - private static Map>[] decoratedImageMap = new Map[LAST_CORNER_KEY]; - + private static Map>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY]; /** * Returns an {@link Image} composed of a base image decorated by another image. * - * @param baseImage the base {@link Image} that should be decorated - * @param decorator the {@link Image} to decorate the base image + * @param baseImage + * the base {@link Image} that should be decorated + * @param decorator + * the {@link Image} to decorate the base image * @return {@link Image} The resulting decorated image */ public static Image decorateImage(Image baseImage, Image decorator) { return decorateImage(baseImage, decorator, BOTTOM_RIGHT); } - /** * Returns an {@link Image} composed of a base image decorated by another image. * - * @param baseImage the base {@link Image} that should be decorated - * @param decorator the {@link Image} to decorate the base image - * @param corner the corner to place decorator image + * @param baseImage + * the base {@link Image} that should be decorated + * @param decorator + * the {@link Image} to decorate the base image + * @param corner + * the corner to place decorator image * @return the resulting decorated {@link Image} */ public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) { if (corner <= 0 || corner >= LAST_CORNER_KEY) { throw new IllegalArgumentException("Wrong decorate corner"); } - Map> cornerDecoratedImageMap = decoratedImageMap[corner]; + Map> cornerDecoratedImageMap = m_decoratedImageMap[corner]; if (cornerDecoratedImageMap == null) { - cornerDecoratedImageMap = new HashMap<>(); - decoratedImageMap[corner] = cornerDecoratedImageMap; + cornerDecoratedImageMap = new HashMap>(); + m_decoratedImageMap[corner] = cornerDecoratedImageMap; } - Map decoratedMap = cornerDecoratedImageMap.computeIfAbsent(baseImage, - k -> new HashMap()); - return decoratedMap.computeIfAbsent(decorator, k -> { + Map decoratedMap = cornerDecoratedImageMap.get(baseImage); + if (decoratedMap == null) { + decoratedMap = new HashMap(); + cornerDecoratedImageMap.put(baseImage, decoratedMap); + } + // + Image result = decoratedMap.get(decorator); + if (result == null) { Rectangle bib = baseImage.getBounds(); Rectangle dib = decorator.getBounds(); - Image result = new Image(Display.getCurrent(), bib.width, bib.height); + // + result = new Image(Display.getCurrent(), bib.width, bib.height); + // GC gc = new GC(result); gc.drawImage(baseImage, 0, 0); - switch (corner) { - case TOP_LEFT: + if (corner == TOP_LEFT) { gc.drawImage(decorator, 0, 0); - break; - case TOP_RIGHT: + } else if (corner == TOP_RIGHT) { gc.drawImage(decorator, bib.width - dib.width, 0); - break; - case BOTTOM_LEFT: + } else if (corner == BOTTOM_LEFT) { gc.drawImage(decorator, 0, bib.height - dib.height); - break; - case BOTTOM_RIGHT: + } else if (corner == BOTTOM_RIGHT) { gc.drawImage(decorator, bib.width - dib.width, bib.height - dib.height); - break; - default: - // do nothing } gc.dispose(); - return result; - }); + // + decoratedMap.put(decorator, result); + } + return result; } - /** * Dispose all of the cached {@link Image}'s. */ public static void disposeImages() { // dispose loaded images - for (Image image : imageMap.values()) { - image.dispose(); + { + for (Image image : m_imageMap.values()) { + image.dispose(); + } + m_imageMap.clear(); } - imageMap.clear(); // dispose decorated images - for (int i = 0; i < decoratedImageMap.length; i++) { - Map> cornerDecoratedImageMap = decoratedImageMap[i]; + for (int i = 0; i < m_decoratedImageMap.length; i++) { + Map> cornerDecoratedImageMap = m_decoratedImageMap[i]; if (cornerDecoratedImageMap != null) { for (Map decoratedMap : cornerDecoratedImageMap.values()) { for (Image image : decoratedMap.values()) { @@ -294,7 +294,6 @@ public class SWTResourceManager { } } } - //////////////////////////////////////////////////////////////////////////// // // Font @@ -303,39 +302,45 @@ public class SWTResourceManager { /** * Maps font names to fonts. */ - private static Map fontMap = new HashMap<>(); + private static Map m_fontMap = new HashMap(); /** * Maps fonts to their bold versions. */ - private static Map fontToBoldFontMap = new HashMap<>(); - + private static Map m_fontToBoldFontMap = new HashMap(); /** * Returns a {@link Font} based on its name, height and style. * - * @param name the name of the font - * @param height the height of the font - * @param style the style of the font + * @param name + * the name of the font + * @param height + * the height of the font + * @param style + * the style of the font * @return {@link Font} The font matching the name, height and style */ public static Font getFont(String name, int height, int style) { return getFont(name, height, style, false, false); } - /** - * Returns a {@link Font} based on its name, height and style. Windows-specific - * strikeout and underline flags are also supported. + * Returns a {@link Font} based on its name, height and style. Windows-specific strikeout and underline + * flags are also supported. * - * @param name the name of the font - * @param size the size of the font - * @param style the style of the font - * @param strikeout the strikeout flag (warning: Windows only) - * @param underline the underline flag (warning: Windows only) - * @return {@link Font} The font matching the name, height, style, strikeout and - * underline + * @param name + * the name of the font + * @param size + * the size of the font + * @param style + * the style of the font + * @param strikeout + * the strikeout flag (warning: Windows only) + * @param underline + * the underline flag (warning: Windows only) + * @return {@link Font} The font matching the name, height, style, strikeout and underline */ public static Font getFont(String name, int size, int style, boolean strikeout, boolean underline) { String fontName = name + '|' + size + '|' + style + '|' + strikeout + '|' + underline; - return fontMap.computeIfAbsent(fontName, k -> { + Font font = m_fontMap.get(fontName); + if (font == null) { FontData fontData = new FontData(name, size, style); if (strikeout || underline) { try { @@ -349,45 +354,47 @@ public class SWTResourceManager { logFontClass.getField("lfUnderline").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$ } } - } catch (Exception e) { + } catch (Throwable e) { + System.err.println("Unable to set underline or strikeout" + " (probably on a non-Windows platform). " + e); //$NON-NLS-1$ //$NON-NLS-2$ } } - return new Font(Display.getCurrent(), fontData); - - }); - + font = new Font(Display.getCurrent(), fontData); + m_fontMap.put(fontName, font); + } + return font; } - /** * Returns a bold version of the given {@link Font}. * - * @param baseFont the {@link Font} for which a bold version is desired + * @param baseFont + * the {@link Font} for which a bold version is desired * @return the bold version of the given {@link Font} */ public static Font getBoldFont(Font baseFont) { - return fontToBoldFontMap.computeIfAbsent(baseFont, k -> { - FontData[] fontDatas = baseFont.getFontData(); + Font font = m_fontToBoldFontMap.get(baseFont); + if (font == null) { + FontData fontDatas[] = baseFont.getFontData(); FontData data = fontDatas[0]; - return new Font(Display.getCurrent(), data.getName(), data.getHeight(), SWT.BOLD); - }); + font = new Font(Display.getCurrent(), data.getName(), data.getHeight(), SWT.BOLD); + m_fontToBoldFontMap.put(baseFont, font); + } + return font; } - /** * Dispose all of the cached {@link Font}'s. */ public static void disposeFonts() { // clear fonts - for (Font font : fontMap.values()) { + for (Font font : m_fontMap.values()) { font.dispose(); } - fontMap.clear(); + m_fontMap.clear(); // clear bold fonts - for (Font font : fontToBoldFontMap.values()) { + for (Font font : m_fontToBoldFontMap.values()) { font.dispose(); } - fontToBoldFontMap.clear(); + m_fontToBoldFontMap.clear(); } - //////////////////////////////////////////////////////////////////////////// // // Cursor @@ -396,38 +403,40 @@ public class SWTResourceManager { /** * Maps IDs to cursors. */ - private static Map idToCursorMap = new HashMap<>(); - + private static Map m_idToCursorMap = new HashMap(); /** * Returns the system cursor matching the specific ID. * - * @param id int The ID value for the cursor + * @param id + * int The ID value for the cursor * @return Cursor The system cursor matching the specific ID */ public static Cursor getCursor(int id) { Integer key = Integer.valueOf(id); - return idToCursorMap.computeIfAbsent(key, k -> new Cursor(Display.getDefault(), id)); + Cursor cursor = m_idToCursorMap.get(key); + if (cursor == null) { + cursor = new Cursor(Display.getDefault(), id); + m_idToCursorMap.put(key, cursor); + } + return cursor; } - /** * Dispose all of the cached cursors. */ public static void disposeCursors() { - for (Cursor cursor : idToCursorMap.values()) { + for (Cursor cursor : m_idToCursorMap.values()) { cursor.dispose(); } - idToCursorMap.clear(); + m_idToCursorMap.clear(); } - //////////////////////////////////////////////////////////////////////////// // // General // //////////////////////////////////////////////////////////////////////////// /** - * Dispose of cached objects and their underlying OS resources. This should only - * be called when the cached objects are no longer needed (e.g. on application - * shutdown). + * Dispose of cached objects and their underlying OS resources. This should only be called when the cached + * objects are no longer needed (e.g. on application shutdown). */ public static void dispose() { disposeColors(); diff --git a/products/com.minres.scviewer.e4.product/scviewer.product b/products/com.minres.scviewer.e4.product/scviewer.product index 3e2be35..fb43cfd 100644 --- a/products/com.minres.scviewer.e4.product/scviewer.product +++ b/products/com.minres.scviewer.e4.product/scviewer.product @@ -80,7 +80,6 @@ - From 93a8c067fc2cbf60bfb5f2526dc673a97b284132 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 3 Jan 2022 14:15:59 +0100 Subject: [PATCH 2/8] add sliuder variant --- .../ui/swt/internal/WaveformView.java | 39 +- .../ui/swt/internal/slider/ImageButton.java | 129 ++ .../ui/swt/internal/slider/RangeSlider.java | 1453 +++++++++++++++++ .../swt/internal/slider/ReflectionUtils.java | 48 + .../slider/SelectionListenerUtil.java | 74 + .../ui/swt/internal/slider/bullet_left.png | Bin 0 -> 307 bytes .../ui/swt/internal/slider/bullet_right.png | Bin 0 -> 307 bytes .../ui/swt/internal/slider/h-slider-drag.png | Bin 0 -> 1057 bytes .../ui/swt/internal/slider/h-slider-hover.png | Bin 0 -> 1057 bytes .../swt/internal/slider/h-slider-normal.png | Bin 0 -> 1055 bytes .../swt/internal/slider/h-slider-selected.png | Bin 0 -> 1041 bytes .../ui/swt/internal/slider/marker_r.png | Bin 0 -> 358 bytes .../ui/swt/internal/slider/marker_r_bl.png | Bin 0 -> 386 bytes .../ui/swt/internal/slider/marker_r_bl_lt.png | Bin 0 -> 366 bytes .../ui/swt/internal/slider/marker_r_lt.png | Bin 0 -> 345 bytes .../ui/swt/internal/slider/slider-drag.png | Bin 0 -> 1085 bytes .../ui/swt/internal/slider/slider-hover.png | Bin 0 -> 1083 bytes .../ui/swt/internal/slider/slider-normal.png | Bin 0 -> 1072 bytes .../swt/internal/slider/slider-selected.png | Bin 0 -> 430 bytes .../org/eclipse/wb/swt/ResourceManager.java | 438 ----- 20 files changed, 1737 insertions(+), 444 deletions(-) create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ReflectionUtils.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/SelectionListenerUtil.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_left.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_right.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-drag.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-hover.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-normal.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-selected.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-drag.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-hover.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-normal.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-selected.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/org/eclipse/wb/swt/ResourceManager.java diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index bbd9525..0deaa44 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -56,13 +56,13 @@ import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; @@ -71,7 +71,6 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ScrollBar; -import org.eclipse.swt.widgets.Slider; import org.eclipse.swt.widgets.Widget; import org.eclipse.wb.swt.SWTResourceManager; @@ -94,6 +93,8 @@ import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; +import com.minres.scviewer.database.ui.swt.internal.slider.ImageButton; +import com.minres.scviewer.database.ui.swt.internal.slider.RangeSlider; import com.minres.scviewer.database.ui.swt.sb.FlatScrollBar; public class WaveformView implements IWaveformView { @@ -345,11 +346,37 @@ public class WaveformView implements IWaveformView { waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider); waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - Composite timeSliderPane = new WaveformSlider(waveformPane, SWT.NONE); - GridData gd_timeSlider = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); - gd_timeSlider.heightHint = 18; - timeSliderPane.setLayoutData(gd_timeSlider); + //Composite timeSliderPane = new WaveformSlider(waveformPane, SWT.NONE); + Composite timeSliderPane = new Composite(waveformPane, SWT.NONE); +// timeSliderPane.setBackground(SWTResourceManager.getColor(SWT.COLOR_RED)); + GridData gd_timeSliderPane = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); +// gd_timeSliderPane.heightHint = 22; + timeSliderPane.setLayoutData(gd_timeSliderPane); + GridLayout gl_timeSliderPane = new GridLayout(3, false); + gl_timeSliderPane.marginHeight=0; + gl_timeSliderPane.marginWidth=0; + gl_timeSliderPane.horizontalSpacing=0; + gl_timeSliderPane.verticalSpacing=0; + timeSliderPane.setLayout(gl_timeSliderPane); + ImageButton b1 = new ImageButton(timeSliderPane, SWT.NONE); + GridData gd_b1 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_b1.widthHint=18; + gd_b1.heightHint=18; + b1.setLayoutData(gd_b1); + b1.setImage(SWTResourceManager.getImage(RangeSlider.class, "bullet_left.png")); + + Composite timeSlider = new RangeSlider(timeSliderPane, SWT.ON|SWT.HIGH|SWT.SMOOTH|SWT.CONTROL); + GridData gd_timeSlide = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); + timeSlider.setLayoutData(gd_timeSlide); + + ImageButton b2 = new ImageButton(timeSliderPane, SWT.NONE); + GridData gd_b2 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_b2.widthHint=18; + gd_b2.heightHint=18; + b2.setLayoutData(gd_b2); + b2.setImage(SWTResourceManager.getImage(RangeSlider.class, "bullet_right.png")); + // create the name pane createTextPane(namePane, "Name"); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java new file mode 100644 index 0000000..21483d6 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java @@ -0,0 +1,129 @@ +package com.minres.scviewer.database.ui.swt.internal.slider; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.graphics.Transform; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; + +public class ImageButton extends Composite +{ + private Color textColor; + private Image image; + private Image grayImage; + private ImageData imageData; + private String text = ""; + private int width; + private int height; + private boolean hover; + + public ImageButton(Composite parent, int style) + { + super(parent, style); + + textColor = Display.getDefault().getSystemColor(SWT.COLOR_WHITE); + + /* Add dispose listener for the image */ + addListener(SWT.Dispose, event -> { + if (image != null) + image.dispose(); + }); + + /* Add custom paint listener that paints the stars */ + addListener(SWT.Paint, event -> { + paintControl(event); + }); + + /* Listen for click events */ + addListener(SWT.MouseDown, event -> { + System.out.println("Click"); + }); + addListener(SWT.MouseDown, event -> { + }); + + addListener(SWT.MouseUp, event -> { + }); + + addListener(SWT.MouseMove, event -> { + hover=false; + redraw(); + }); + + addListener(SWT.MouseWheel, event -> { + }); + + addListener(SWT.MouseHover, event -> { + hover=true; + redraw(); + }); + + addListener(SWT.MouseDoubleClick, event -> { + }); + } + + private void paintControl(Event event) { + GC gc = event.gc; + + if (image != null) + { +// gc.drawImage(image, 1, 1); +// if(hover) { +// Rectangle rect = image.getBounds (); +// Transform tr = new Transform (event.display); +// tr.setElements (1, 0, 0, -1, 1, 2*(1+rect.height)); +// gc.setTransform (tr); +// gc.drawImage (image, 1, 1); +// gc.setTransform (null); +// } + if(hover) { + gc.drawImage(image, 1, 1); + } else { + gc.drawImage(grayImage, 1, 1); + } + Point textSize = gc.textExtent(text); + gc.setForeground(textColor); + gc.drawText(text, (width - textSize.x) / 2 + 1, (height - textSize.y) / 2 + 1, true); + } + } + + public void setImage(Image img) + { + image = new Image(Display.getDefault(), img, SWT.IMAGE_COPY); + grayImage = new Image(Display.getDefault(),img,SWT.IMAGE_GRAY); + width = img.getBounds().width; + height = img.getBounds().height; + imageData = img.getImageData(); + redraw(); + } + + public void setText(String text) + { + this.text = text; + redraw(); + } + + @Override + public Point computeSize(int wHint, int hHint, boolean changed) + { + int overallWidth = width; + int overallHeight = height; + + /* Consider hints */ + if (wHint != SWT.DEFAULT && wHint < overallWidth) + overallWidth = wHint; + + if (hHint != SWT.DEFAULT && hHint < overallHeight) + overallHeight = hHint; + + /* Return computed dimensions plus border */ + return new Point(overallWidth + 2, overallHeight + 2); + } + +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java new file mode 100644 index 0000000..d146b53 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java @@ -0,0 +1,1453 @@ +package com.minres.scviewer.database.ui.swt.internal.slider; + +import java.text.Format; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Widget; +import org.eclipse.wb.swt.SWTResourceManager; + +/** + * Instances of this class provide a slider with two thumbs to control lower and + * upper integer values. + *

+ *

+ *
Styles:
+ *
BORDER
+ *
HORIZONTAL
+ *
VERTICAL
+ *
CONTROL - Allow key and mouse manipulation to control both lower and + * upper value thumbs simultaneously
+ *
ON - Indicates that selection listeners are notified continuously during + * thumb drag events. Otherwise, notification occurs only after the drag event + * terminates.
+ *
HIGH - Indicates high quality tick marks are generated dynamically to a + * factor of the pageIncrement or increment. Otherwise, tick marks divide the + * scale evenly into ten parts.
+ *
SMOOTH - Indicates mouse manipulation of upper and lower values are + * computed smoothly from the exact mouse cursor position disregarding the + * increment value. Otherwise, values are constrained to an incremental + * value.
+ *
Events:
+ *
Selection
+ *
+ *

+ *

+ * Note: Styles HORIZONTAL and VERTICAL are mutually exclusive. + *

+ */ +public class RangeSlider extends Canvas { + + private static final byte NONE = 0; + private static final byte UPPER = 1 << 0; + private static final byte LOWER = 1 << 1; + private static final byte BOTH = UPPER | LOWER; + + private static int minWidth = 18; + private static int minHeight = 18; + private static int imgWidth = 8; + private int minimum; + private int maximum; + private int lowerValue; + private int upperValue; + private final Image slider, sliderHover, sliderDrag, sliderSelected; + private final Image vSlider, vSliderHover, vSliderDrag, vSliderSelected; + private int orientation; + private int increment; + private int pageIncrement; + private byte selectedElement, priorSelectedElement; + private boolean dragInProgress; + private boolean upperHover, lowerHover; + private int previousUpperValue, previousLowerValue; + private int startDragUpperValue, startDragLowerValue; + private Point startDragPoint; + private boolean hasFocus; + private final boolean isSmooth; + private final boolean isFullSelection; + private final boolean isHighQuality; + private final boolean isOn; + private Format toolTipFormatter; + private String clientToolTipText; + + /** + * Constructs a new instance of this class given its parent and a style value + * describing its behavior and appearance. + *

+ * The style value is either one of the style constants defined in class + * SWT which is applicable to instances of this class, or must be + * built by bitwise OR'ing together (that is, using the + * int "|" operator) two or more of those SWT style + * constants. The class description lists the style constants that are + * applicable to the class. Style bits are also inherited from superclasses. + *

+ * + * @param parent a composite control which will be the parent of the new + * instance (cannot be null) + * @param style the style of control to construct. Default style is HORIZONTAL + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the parent
  • + *
+ * @see SWT#HORIZONTAL + * @see SWT#VERTICAL + * @see Widget#getStyle + * + */ + public RangeSlider(final Composite parent, final int style) { + super(parent, SWT.DOUBLE_BUFFERED | ((style & SWT.BORDER) == SWT.BORDER ? SWT.BORDER : SWT.NONE)); + minimum = lowerValue = 0; + maximum = upperValue = 100; + increment = 1; + pageIncrement = 10; + slider = SWTResourceManager.getImage(this.getClass(), "marker_r.png"); + sliderHover = SWTResourceManager.getImage(this.getClass(), "marker_r_lt.png"); + sliderDrag = SWTResourceManager.getImage(this.getClass(), "marker_r_bl.png"); + sliderSelected = SWTResourceManager.getImage(this.getClass(), "marker_r_bl_lt.png"); + + vSlider = SWTResourceManager.getImage(this.getClass(), "h-slider-normal.png"); + vSliderHover = SWTResourceManager.getImage(this.getClass(), "h-slider-hover.png"); + vSliderDrag = SWTResourceManager.getImage(this.getClass(), "h-slider-drag.png"); + vSliderSelected = SWTResourceManager.getImage(this.getClass(), "h-slider-selected.png"); + + if ((style & SWT.VERTICAL) == SWT.VERTICAL) { + orientation = SWT.VERTICAL; + } else { + orientation = SWT.HORIZONTAL; + } + isSmooth = (style & SWT.SMOOTH) == SWT.SMOOTH; + isFullSelection = (style & SWT.CONTROL) == SWT.CONTROL; + isHighQuality = (style & SWT.HIGH) == SWT.HIGH; + isOn = (style & SWT.ON) == SWT.ON; + selectedElement = isFullSelection ? BOTH : LOWER; + +// addListener(SWT.Dispose, event -> { +// SWTResourceManager.dsafeDispose(slider); +// SWTGraphicUtil.safeDispose(sliderHover); +// SWTGraphicUtil.safeDispose(sliderDrag); +// SWTGraphicUtil.safeDispose(sliderSelected); +// +// SWTGraphicUtil.safeDispose(vSlider); +// SWTGraphicUtil.safeDispose(vSliderHover); +// SWTGraphicUtil.safeDispose(vSliderDrag); +// SWTGraphicUtil.safeDispose(vSliderSelected); +// }); + addMouseListeners(); + addListener(SWT.Resize, event -> { + }); + addListener(SWT.FocusIn, e -> { + hasFocus = true; + redraw(); + }); + addListener(SWT.FocusOut, e -> { + hasFocus = false; + redraw(); + }); + addListener(SWT.KeyDown, event -> { + handleKeyDown(event); + }); + addPaintListener(event -> { + drawWidget(event); + }); + } + + @Override + public int getStyle() { + return super.getStyle() | orientation | (isSmooth ? SWT.SMOOTH : SWT.NONE) | // + (isOn ? SWT.ON : SWT.NONE) | // + (isFullSelection ? SWT.CONTROL : SWT.NONE) | // + (isHighQuality ? SWT.HIGH : SWT.NONE); + } + + /** + * Add the mouse listeners (mouse up, mouse down, mouse move, mouse wheel) + */ + private void addMouseListeners() { + addListener(SWT.MouseDown, event -> { + handleMouseDown(event); + }); + + addListener(SWT.MouseUp, event -> { + handleMouseUp(event); + }); + + addListener(SWT.MouseMove, event -> { + handleMouseMove(event); + }); + + addListener(SWT.MouseWheel, event -> { + handleMouseWheel(event); + }); + + addListener(SWT.MouseHover, event -> { + handleMouseHover(event); + }); + + addListener(SWT.MouseDoubleClick, event -> { + handleMouseDoubleClick(event); + }); + } + + /** + * Code executed when the mouse is down + * + * @param e event + */ + private void handleMouseDown(final Event e) { + selectKnobs(e); + if (e.count == 1) { + priorSelectedElement = selectedElement; + } + if (upperHover || lowerHover) { + selectedElement = isFullSelection && lowerHover && upperHover ? BOTH : lowerHover ? LOWER : upperHover ? UPPER : selectedElement; + dragInProgress = true; + startDragLowerValue = previousLowerValue = lowerValue; + startDragUpperValue = previousUpperValue = upperValue; + startDragPoint = new Point(e.x, e.y); + } + } + + /** + * Code executed when the mouse is up + * + * @param e event + */ + private void handleMouseUp(final Event e) { + if (dragInProgress) { + startDragPoint = null; + validateNewValues(e); + dragInProgress = false; + super.setToolTipText(clientToolTipText); + } + } + + /** + * invoke selection listeners if either upper or lower value has changed. if + * listeners reject the change, restore the previous values. redraw if either + * upper or lower value has changed. + * + * @param e event + */ + private void validateNewValues(final Event e) { + if (upperValue != previousUpperValue || lowerValue != previousLowerValue) { + if (!SelectionListenerUtil.fireSelectionListeners(this,e)) { + upperValue = previousUpperValue; + lowerValue = previousLowerValue; + } + previousUpperValue = upperValue; + previousLowerValue = lowerValue; + redraw(); + } + } + + + /** + * Code executed when the mouse pointer is moving + * + * @param e event + */ + private void handleMouseMove(final Event e) { + if (!dragInProgress) { + final boolean wasUpper = upperHover; + final boolean wasLower = lowerHover; + selectKnobs(e); + if (wasUpper != upperHover || wasLower != lowerHover) { + redraw(); + } + } else { // dragInProgress + final int x = e.x, y = e.y; + if (orientation == SWT.HORIZONTAL) { + if (selectedElement == BOTH) { + final int diff = (int) ((startDragPoint.x - x) / computePixelSizeForHorizontalSlider()) + minimum; + int newUpper = startDragUpperValue - diff; + int newLower = startDragLowerValue - diff; + if (newUpper > maximum) { + newUpper = maximum; + newLower = maximum - (startDragUpperValue - startDragLowerValue); + } else if (newLower < minimum) { + newLower = minimum; + newUpper = minimum + startDragUpperValue - startDragLowerValue; + } + upperValue = newUpper; + lowerValue = newLower; + if (!isSmooth) { + lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; + upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; + } + handleToolTip(lowerValue, upperValue); + } else if ((selectedElement & UPPER) != 0) { + upperValue = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; + if (!isSmooth) { + upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; + } + checkUpperValue(); + handleToolTip(upperValue); + } else { + lowerValue = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; + if (!isSmooth) { + lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; + } + checkLowerValue(); + handleToolTip(lowerValue); + } + } else { + if (selectedElement == BOTH) { + final int diff = (int) ((startDragPoint.y - y) / computePixelSizeForVerticalSlider()) + minimum; + int newUpper = startDragUpperValue - diff; + int newLower = startDragLowerValue - diff; + if (newUpper > maximum) { + newUpper = maximum; + newLower = maximum - (startDragUpperValue - startDragLowerValue); + } else if (newLower < minimum) { + newLower = minimum; + newUpper = minimum + startDragUpperValue - startDragLowerValue; + } + upperValue = newUpper; + lowerValue = newLower; + if (!isSmooth) { + lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; + upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; + } + handleToolTip(lowerValue, upperValue); + } else if ((selectedElement & UPPER) != 0) { + upperValue = (int) Math.round((y - 9d) / computePixelSizeForVerticalSlider()) + minimum; + if (!isSmooth) { + upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; + } + checkUpperValue(); + handleToolTip(upperValue); + } else { + lowerValue = (int) Math.round((y - 9d) / computePixelSizeForVerticalSlider()) + minimum; + if (!isSmooth) { + lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; + } + checkLowerValue(); + handleToolTip(lowerValue); + } + } + if (isOn) { + validateNewValues(e); + } else { + redraw(); + } + } + } + + /** + * determine whether the input coordinate is within the scale bounds and between + * the current upper and lower values. + * + * @param x + * @param y + * @return + */ + private boolean isBetweenKnobs(int x, int y) { + return orientation == SWT.HORIZONTAL ? x < coordUpper.x && x > coordLower.x && y >= minHeight/3 && y <= minHeight/3 + getClientArea().height - 2*minHeight/3 : // + y < coordUpper.y && y > coordLower.y && x >= minWidth/3 && x <= minWidth/3 + getClientArea().width - 2*minWidth/3; + } + + /** + * set the upperHover and lowerHover values according to the coordinates of the + * input event, the key modifier state, and whether the style allows selection + * of both knobs. + * + * @param e + */ + private void selectKnobs(final Event e) { + if (coordLower == null) { + return; + } + final Image img = orientation == SWT.HORIZONTAL ? slider : vSlider; + final int x = e.x, y = e.y; + lowerHover = x >= coordLower.x && x <= coordLower.x + img.getBounds().width && y >= coordLower.y && y <= coordLower.y + img.getBounds().height; + upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && // + x >= coordUpper.x && x <= coordUpper.x + img.getBounds().width && // + y >= coordUpper.y && y <= coordUpper.y + img.getBounds().height; + lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover; + if (!lowerHover && !upperHover && isFullSelection && isBetweenKnobs(x, y)) { + lowerHover = upperHover = true; + } + } + + /** + * if the input coordinate is within the scale bounds, return the corresponding + * scale value of the coordinate. otherwise return -1. + * + * @param x x coordinate value + * @param y y coordinate value + * @return + */ + private int getCursorValue(int x, int y) { + int value = -1; + final Rectangle clientArea = getClientArea(); + if (orientation == SWT.HORIZONTAL) { + if (x < 9 + clientArea.width - 20 && x >= 9 && y >= 9 && y <= 9 + clientArea.height - 20) { + value = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; + } + } else if (y < 9 + clientArea.height - 20 && y >= 9 && x >= 9 && x <= 9 + clientArea.width - 20) { + value = (int) Math.round((y - 9d) / computePixelSizeForVerticalSlider()) + minimum; + } + return value; + } + + /** + * Code executed when the mouse double click + * + * @param e event + */ + private void handleMouseDoubleClick(final Event e) { + final int value = getCursorValue(e.x, e.y); + if (value >= 0) { + selectedElement = priorSelectedElement; + if (value > upperValue) { + if (selectedElement == BOTH) { + lowerValue += value - upperValue; + upperValue = value; + } else if ((selectedElement & UPPER) != 0) { + upperValue = value; + } else if ((selectedElement & LOWER) != 0) { + final int diff = upperValue - lowerValue; + if (value + diff > maximum) { + upperValue = maximum; + lowerValue = maximum - diff; + } else { + upperValue = value + diff; + lowerValue = value; + } + } + } else if (value < lowerValue) { + if (selectedElement == BOTH) { + upperValue += value - lowerValue; + lowerValue = value; + } else if ((selectedElement & LOWER) != 0) { + lowerValue = value; + } else if ((selectedElement & UPPER) != 0) { + final int diff = upperValue - lowerValue; + if (value - diff < minimum) { + lowerValue = minimum; + upperValue = minimum + diff; + } else { + upperValue = value; + lowerValue = value - diff; + } + } + } else if (value > lowerValue && value < upperValue && selectedElement != BOTH) { + if ((selectedElement & LOWER) != 0) { + lowerValue = value; + } else if ((selectedElement & UPPER) != 0) { + upperValue = value; + } + } + validateNewValues(e); + } + } + + private StringBuffer toolTip; + private Point coordUpper; + private Point coordLower; + + /** + * set the tooltip if a toolTipFormatter is present. either one or two values + * are accepted. + * + * @param values + */ + private void handleToolTip(int... values) { + if (toolTipFormatter != null) { + try { + if (values.length == 1) { + toolTip.setLength(0); + toolTipFormatter.format(values[0], toolTip, null); + super.setToolTipText(toolTip.toString()); + } else if (values.length == 2) { + toolTip.setLength(0); + toolTipFormatter.format(values[0], toolTip, null); + toolTip.append(" \u2194 "); // LEFT RIGHT ARROW + toolTipFormatter.format(values[1], toolTip, null); + super.setToolTipText(toolTip.toString()); + } + } catch (final IllegalArgumentException ex) { + super.setToolTipText(clientToolTipText); + } + } + } + + /** + * Code executed on mouse hover + * + * @param e event + */ + private void handleMouseHover(final Event e) { + if (!dragInProgress && toolTipFormatter != null) { + final int value = getCursorValue(e.x, e.y); + if (value >= 0) { + try { + toolTip.setLength(0); + toolTipFormatter.format(value, toolTip, null); + super.setToolTipText(toolTip.toString()); + } catch (final IllegalArgumentException ex) { + super.setToolTipText(clientToolTipText); + } + } else { + super.setToolTipText(clientToolTipText); + } + } + } + + /** + * a formatter for displaying a tool tip when hovering over the scale and during + * thumb modification events. The + * {@link Format#format(Object, StringBuffer, java.text.FieldPosition)} method + * is invoked to retrieve the text for the tooltip where the input + * {@code Object} is an {@code Integer} with a value within the minimum and + * maximum. + * + * @param formatter + */ + public void setToolTipFormatter(Format formatter) { + toolTip = formatter != null ? new StringBuffer() : null; + toolTipFormatter = formatter; + } + + @Override + public void setToolTipText(String string) { + super.setToolTipText(clientToolTipText = string); + } + + /** + * Code executed when the mouse wheel is activated + * + * @param e event + */ + private void handleMouseWheel(final Event e) { + if (selectedElement == NONE || dragInProgress) { + e.doit = false; // we are consuming this event + return; + } + previousLowerValue = lowerValue; + previousUpperValue = upperValue; + final int amount = increment * ((e.stateMask & SWT.SHIFT) != 0 ? 10 : (e.stateMask & SWT.CTRL) != 0 ? 2 : 1); + if (selectedElement == BOTH) { + int newLower = lowerValue + e.count * amount; + int newUpper = upperValue + e.count * amount; + if (newUpper > maximum) { + newUpper = maximum; + newLower = maximum - (upperValue - lowerValue); + } else if (newLower < minimum) { + newLower = minimum; + newUpper = minimum + upperValue - lowerValue; + } + upperValue = newUpper; + lowerValue = newLower; + } else if ((selectedElement & LOWER) != 0) { + lowerValue += e.count * amount; + checkLowerValue(); + } else { + upperValue += e.count * amount; + checkUpperValue(); + } + validateNewValues(e); + e.doit = false; // we are consuming this event + } + + /** + * Check if the lower value is in ranges + */ + private void checkLowerValue() { + if (lowerValue < minimum) { + lowerValue = minimum; + } + if (lowerValue > maximum) { + lowerValue = maximum; + } + if (lowerValue > upperValue) { + lowerValue = upperValue; + } + } + + /** + * Check if the upper value is in ranges + */ + private void checkUpperValue() { + if (upperValue < minimum) { + upperValue = minimum; + } + if (upperValue > maximum) { + upperValue = maximum; + } + if (upperValue < lowerValue) { + upperValue = lowerValue; + } + } + + /** + * Draws the widget + * + * @param e paint event + */ + private void drawWidget(final PaintEvent e) { + final Rectangle rect = getClientArea(); + if (rect.width == 0 || rect.height == 0) { + return; + } + e.gc.setAdvanced(true); + e.gc.setAntialias(SWT.ON); + if (orientation == SWT.HORIZONTAL) { + drawHorizontalRangeSlider(e.gc); + } else { + drawVerticalRangeSlider(e.gc); + } + + } + + /** + * Draw the range slider (horizontal) + * + * @param gc graphic context + */ + private void drawHorizontalRangeSlider(final GC gc) { + drawBackgroundHorizontal(gc); + drawBarsHorizontal(gc); + if (lowerHover || (selectedElement & LOWER) != 0) { + coordUpper = drawHorizontalKnob(gc, upperValue, true); + coordLower = drawHorizontalKnob(gc, lowerValue, false); + } else { + coordLower = drawHorizontalKnob(gc, lowerValue, false); + coordUpper = drawHorizontalKnob(gc, upperValue, true); + } + } + + /** + * Draw the background + * + * @param gc graphic context + */ + private void drawBackgroundHorizontal(final GC gc) { + final Rectangle clientArea = getClientArea(); + + gc.setBackground(getBackground()); + gc.fillRectangle(clientArea); + + if (isEnabled()) { + gc.setForeground(getForeground()); + } else { + gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); + } + gc.drawRoundRectangle(minHeight/3+imgWidth, minHeight/3, clientArea.width - 2*(minHeight/3+imgWidth), clientArea.height - 2*minHeight/3+3, 3, 3); + + final float pixelSize = computePixelSizeForHorizontalSlider(); + final int startX = (int) (pixelSize * lowerValue); + final int endX = (int) (pixelSize * upperValue); + if (isEnabled()) { + gc.setBackground(getForeground()); + } else { + gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); + } + gc.fillRectangle(minHeight/3+3 + startX, minHeight/3, endX - startX - 3, clientArea.height - 2*minHeight/3+3); + + } + + /** + * @return how many pixels corresponds to 1 point of value + */ + private float computePixelSizeForHorizontalSlider() { + return (getClientArea().width - 20f) / (maximum - minimum); + } + + /** + * Draw the bars + * + * @param gc graphic context + */ + private void drawBarsHorizontal(final GC gc) { + } + + /** + * Draws an horizontal knob + * + * @param gc graphic context + * @param value corresponding value + * @param upper if true, draws the upper knob. If + * false, draws the lower knob + * @return the coordinate of the upper left corner of the knob + */ + private Point drawHorizontalKnob(final GC gc, final int value, final boolean upper) { + final float pixelSize = computePixelSizeForHorizontalSlider(); + final int x = (int) (pixelSize * value); + Image image; + if (upper) { + if (upperHover) { + image = dragInProgress || (selectedElement & UPPER) != 0 ? sliderDrag : sliderHover; + } else if ((selectedElement & UPPER) != 0 && !lowerHover) { + image = hasFocus ? sliderSelected : sliderHover; + } else { + image = slider; + } + } else { + if (lowerHover) { + image = dragInProgress || (selectedElement & LOWER) != 0 ? sliderDrag : sliderHover; + } else if ((selectedElement & LOWER) != 0 && !upperHover) { + image = hasFocus ? sliderSelected : sliderHover; + } else { + image = slider; + } + } + if (isEnabled()) { + gc.drawImage(image, x + 5, getClientArea().height / 2 - slider.getBounds().height / 2); + } else { + final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE); + gc.drawImage(temp, x + 5, getClientArea().height / 2 - slider.getBounds().height / 2); + temp.dispose(); + } + return new Point(x + 5, getClientArea().height / 2 - slider.getBounds().height / 2); + } + + /** + * Draw the range slider (vertical) + * + * @param gc graphic context + */ + private void drawVerticalRangeSlider(final GC gc) { + drawBackgroundVertical(gc); + drawBarsVertical(gc); + if (lowerHover || (selectedElement & LOWER) != 0) { + coordUpper = drawVerticalKnob(gc, upperValue, true); + coordLower = drawVerticalKnob(gc, lowerValue, false); + } else { + coordLower = drawVerticalKnob(gc, lowerValue, false); + coordUpper = drawVerticalKnob(gc, upperValue, true); + } + } + + /** + * Draws the background + * + * @param gc graphic context + */ + private void drawBackgroundVertical(final GC gc) { + final Rectangle clientArea = getClientArea(); + gc.setBackground(getBackground()); + gc.fillRectangle(clientArea); + + if (isEnabled()) { + gc.setForeground(getForeground()); + } else { + gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); + } + gc.drawRoundRectangle(9, 9, clientArea.width - 20, clientArea.height - 20, 3, 3); + + final float pixelSize = computePixelSizeForVerticalSlider(); + final int startY = (int) (pixelSize * lowerValue); + final int endY = (int) (pixelSize * upperValue); + if (isEnabled()) { + gc.setBackground(getForeground()); + } else { + gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); + } + gc.fillRectangle(9, 12 + startY, clientArea.width - 20, endY - startY - 6); + + } + + /** + * @return how many pixels corresponds to 1 point of value + */ + private float computePixelSizeForVerticalSlider() { + return (getClientArea().height - 20f) / (maximum - minimum); + } + + /** + * Draws the bars + * + * @param gc graphic context + */ + private void drawBarsVertical(final GC gc) { + final Rectangle clientArea = getClientArea(); + if (isEnabled()) { + gc.setForeground(getForeground()); + } else { + gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); + } + } + + /** + * Draws a vertical knob + * + * @param gc graphic context + * @param value corresponding value + * @param upper if true, draws the upper knob. If + * false, draws the lower knob + * @return the coordinate of the upper left corner of the knob + */ + private Point drawVerticalKnob(final GC gc, final int value, final boolean upper) { + final float pixelSize = computePixelSizeForVerticalSlider(); + final int y = (int) (pixelSize * value); + + Image image; + if (upper) { + if (upperHover) { + image = dragInProgress || (selectedElement & UPPER) != 0 ? vSliderDrag : vSliderHover; + } else if ((selectedElement & UPPER) != 0 && !lowerHover) { + image = hasFocus ? vSliderSelected : vSliderHover; + } else { + image = vSlider; + } + } else { + if (lowerHover) { + image = dragInProgress || (selectedElement & LOWER) != 0 ? vSliderDrag : vSliderHover; + } else if ((selectedElement & LOWER) != 0 && !upperHover) { + image = hasFocus ? vSliderSelected : vSliderHover; + } else { + image = vSlider; + } + } + + if (isEnabled()) { + gc.drawImage(image, getClientArea().width / 2 - 8, y + 4); + } else { + final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE); + gc.drawImage(temp, getClientArea().width / 2 - 8, y + 4); + temp.dispose(); + } + return new Point(getClientArea().width / 2 - 8, y + 4); + } + + /** + * move the cursor location by the input delta values. + * + * @param xDelta + * @param yDelta + */ + private void moveCursorPosition(int xDelta, int yDelta) { + final Point cursorPosition = getDisplay().getCursorLocation(); + cursorPosition.x += xDelta; + cursorPosition.y += yDelta; + getDisplay().setCursorLocation(cursorPosition); + } + + /** + * Code executed when a key is typed + * + * @param event event + */ + private void handleKeyDown(final Event event) { + // TODO consider API for setting accelerator values + int accelerator = (event.stateMask & SWT.SHIFT) != 0 ? 10 : (event.stateMask & SWT.CTRL) != 0 ? 2 : 1; + if (dragInProgress) { + switch (event.keyCode) { + case SWT.ESC: + startDragPoint = null; + upperValue = startDragUpperValue; + lowerValue = startDragLowerValue; + validateNewValues(event); + dragInProgress = false; + if (!isOn) { + redraw(); + } + event.doit = false; + break; + case SWT.ARROW_UP: + accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; + case SWT.ARROW_LEFT: + if (orientation == SWT.VERTICAL) { + moveCursorPosition(0, -accelerator); + } else { + moveCursorPosition(-accelerator, 0); + } + event.doit = false; + break; + case SWT.ARROW_DOWN: + accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; + case SWT.ARROW_RIGHT: + if (orientation == SWT.VERTICAL) { + moveCursorPosition(0, accelerator); + } else { + moveCursorPosition(accelerator, 0); + } + event.doit = false; + break; + } + return; + } + previousLowerValue = lowerValue; + previousUpperValue = upperValue; + + if (selectedElement == NONE) { + selectedElement = LOWER; + } + switch (event.keyCode) { + case SWT.HOME: + if (selectedElement == BOTH) { + if ((event.stateMask & SWT.SHIFT) != 0) { + lowerValue = maximum - (upperValue - lowerValue); + upperValue = maximum; + } else { + upperValue = minimum + upperValue - lowerValue; + lowerValue = minimum; + } + } else if ((selectedElement & UPPER) != 0) { + upperValue = maximum; + } else { + lowerValue = minimum; + } + break; + case SWT.END: + if (selectedElement == BOTH) { + if ((event.stateMask & SWT.SHIFT) != 0) { + upperValue = minimum + upperValue - lowerValue; + lowerValue = minimum; + } else { + lowerValue = maximum - (upperValue - lowerValue); + upperValue = maximum; + } + } else if ((selectedElement & UPPER) != 0) { + upperValue = lowerValue; + } else { + lowerValue = upperValue; + } + break; + case SWT.PAGE_UP: + accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; + if (selectedElement == BOTH) { + translateValues(pageIncrement * -accelerator); + } else if ((selectedElement & UPPER) != 0) { + upperValue -= pageIncrement * accelerator; + } else { + lowerValue -= pageIncrement * accelerator; + } + break; + case SWT.PAGE_DOWN: + accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; + if (selectedElement == BOTH) { + translateValues(pageIncrement * accelerator); + } else if ((selectedElement & UPPER) != 0) { + upperValue += pageIncrement * accelerator; + } else { + lowerValue += pageIncrement * accelerator; + } + break; + case SWT.ARROW_DOWN: + accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; + case SWT.ARROW_RIGHT: + if (selectedElement == BOTH) { + translateValues(accelerator * increment); + } else if ((selectedElement & UPPER) != 0) { + upperValue += accelerator * increment; + } else { + lowerValue += accelerator * increment; + } + break; + case SWT.ARROW_UP: + accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; + case SWT.ARROW_LEFT: + if (selectedElement == BOTH) { + translateValues(-accelerator * increment); + } else if ((selectedElement & UPPER) != 0) { + upperValue -= accelerator * increment; + } else { + lowerValue -= accelerator * increment; + } + break; + case SWT.TAB: + final boolean next = (event.stateMask & SWT.SHIFT) == 0; + if (next && (selectedElement & LOWER) != 0) { + selectedElement = isFullSelection && selectedElement == LOWER ? BOTH : UPPER; + redraw(); + } else if (!next && (selectedElement & UPPER) != 0) { + selectedElement = isFullSelection && selectedElement == UPPER ? BOTH : LOWER; + redraw(); + } else { + traverse(next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS); + } + return; + } + if (previousLowerValue != lowerValue || previousUpperValue != upperValue) { + if (selectedElement == BOTH) { + checkLowerValue(); + checkUpperValue(); + } else if ((selectedElement & UPPER) != 0) { + checkUpperValue(); + } else { + checkLowerValue(); + } + validateNewValues(event); + } + } + + /** + * translate both the upper and lower values by the input amount. The updated + * values are constrained to be within the minimum and maximum. The difference + * between upper and lower values is retained. + * + * @param amount + */ + private void translateValues(int amount) { + int newLower = lowerValue + amount; + int newUpper = upperValue + amount; + if (newUpper > maximum) { + newUpper = maximum; + newLower = maximum - (upperValue - lowerValue); + } else if (newLower < minimum) { + newLower = minimum; + newUpper = minimum + upperValue - lowerValue; + } + upperValue = newUpper; + lowerValue = newLower; + } + + /** + * Adds the listener to the collection of listeners who will be notified when + * the user changes the receiver's value, by sending it one of the messages + * defined in the SelectionListener interface. + *

+ * widgetSelected is called when the user changes the receiver's + * value. widgetDefaultSelected is not called. + *

+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see SelectionListener + * @see #removeSelectionListener + */ + public void addSelectionListener(final SelectionListener listener) { + checkWidget(); + SelectionListenerUtil.addSelectionListener(this, listener); + } + + /** + * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean) + */ + @Override + public Point computeSize(final int wHint, final int hHint, final boolean changed) { + final int width, height; + checkWidget(); + if (orientation == SWT.HORIZONTAL) { + if (wHint < 100) { + width = 100; + } else { + width = wHint; + } + + if (hHint < minHeight) { + height = minHeight; + } else { + height = hHint; + } + } else { + if (wHint < minWidth) { + width = minWidth; + } else { + width = wHint; + } + + if (hHint < 100) { + height = 100; + } else { + height = hHint; + } + } + + return new Point(width, height); + } + + /** + * Returns the amount that the selected receiver's value will be modified by + * when the up/down (or right/left) arrows are pressed. + * + * @return the increment + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getIncrement() { + checkWidget(); + return increment; + } + + /** + * Returns the 'lower selection', which is the lower receiver's position. + * + * @return the selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getLowerValue() { + checkWidget(); + return lowerValue; + } + + /** + * Returns the maximum value which the receiver will allow. + * + * @return the maximum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getMaximum() { + checkWidget(); + return maximum; + } + + /** + * Returns the minimum value which the receiver will allow. + * + * @return the minimum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getMinimum() { + checkWidget(); + return minimum; + } + + /** + * Returns the amount that the selected receiver's value will be modified by + * when the page increment/decrement areas are selected. + * + * @return the page increment + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getPageIncrement() { + checkWidget(); + return pageIncrement; + } + + /** + * Returns the 'selection', which is an array where the first element is the + * lower selection, and the second element is the upper selection + * + * @return the selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int[] getSelection() { + checkWidget(); + final int[] selection = new int[2]; + selection[0] = lowerValue; + selection[1] = upperValue; + return selection; + } + + /** + * Returns the 'upper selection', which is the upper receiver's position. + * + * @return the selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public int getUpperValue() { + checkWidget(); + return upperValue; + } + + /** + * Removes the listener from the collection of listeners who will be notified + * when the user changes the receiver's value. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see SelectionListener + * @see #addSelectionListener + */ + public void removeSelectionListener(final SelectionListener listener) { + checkWidget(); + SelectionListenerUtil.removeSelectionListener(this, listener); + } + + /** + * Sets the amount that the selected receiver's value will be modified by when + * the up/down (or right/left) arrows are pressed to the argument, which must be + * at least one. + * + * @param increment the new increment (must be greater than zero) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setIncrement(final int increment) { + checkWidget(); + this.increment = increment; + redraw(); + } + + /** + * Sets the 'lower selection', which is the receiver's lower value, to the input + * argument which must be less than or equal to the current 'upper selection' + * and greater or equal to the minimum. If either condition fails, no action is + * taken. + * + * @param value the new lower selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * @see #getUpperValue() + * @see #getMinimum() + * @see #setSelection(int, int) + */ + public void setLowerValue(final int value) { + setSelection(value, upperValue); + } + + /** + * Sets the maximum value that the receiver will allow. This new value will be + * ignored if it is not greater than the receiver's current minimum value. If + * the new maximum is applied then the receiver's selection value will be + * adjusted if necessary to fall within its new range. + * + * @param value the new maximum, which must be greater than the current minimum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * @see #setExtrema(int, int) + */ + public void setMaximum(final int value) { + setExtrema(minimum, value); + } + + /** + * Sets the minimum value that the receiver will allow. This new value will be + * ignored if it is negative or is not less than the receiver's current maximum + * value. If the new minimum is applied then the receiver's selection value will + * be adjusted if necessary to fall within its new range. + * + * @param value the new minimum, which must be nonnegative and less than the + * current maximum + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * @see #setExtrema(int, int) + */ + public void setMinimum(final int value) { + setExtrema(value, maximum); + } + + /** + * Sets the minimum and maximum values that the receiver will allow. The new + * values will be ignored if either are negative or the min value is not less + * than the max. The receiver's selection values will be adjusted if necessary + * to fall within the new range. + * + * @param min the new minimum, which must be nonnegative and less than the max + * @param max the new maximum, which must be greater than the min + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setExtrema(final int min, final int max) { + checkWidget(); + if (min >= 0 && min < max && (min != minimum || max != maximum)) { + minimum = min; + maximum = max; + if (lowerValue < minimum) { + lowerValue = minimum; + } else if (lowerValue > maximum) { + lowerValue = maximum; + } + if (upperValue < minimum) { + upperValue = minimum; + } else if (upperValue > maximum) { + upperValue = maximum; + } + redraw(); + } + } + + /** + * Sets the amount that the receiver's value will be modified by when the page + * increment/decrement areas are selected to the argument, which must be at + * least one. + * + * @param pageIncrement the page increment (must be greater than zero) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setPageIncrement(final int pageIncrement) { + checkWidget(); + this.pageIncrement = pageIncrement; + redraw(); + } + + /** + * Sets the 'selection', which is the receiver's value. The lower value must be + * less than or equal to the upper value. Additionally, both values must be + * inclusively between the slider minimum and maximum. If either condition + * fails, no action is taken. + * + * @param value the new selection (first value is lower value, second value is + * upper value) + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ */ + public void setSelection(final int[] values) { + if (values.length == 2) { + setSelection(values[0], values[1]); + } + } + + /** + * Sets the 'selection', which is the receiver's value. The lower value must be + * less than or equal to the upper value. Additionally, both values must be + * inclusively between the slider minimum and maximum. If either condition + * fails, no action is taken. + * + * @param lowerValue the new lower selection + * @param upperValue the new upper selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * @see #getMinimum() + * @see #getMaximum() + */ + public void setSelection(final int lowerValue, final int upperValue) { + checkWidget(); + if (lowerValue <= upperValue && lowerValue >= minimum && upperValue <= maximum && (this.lowerValue != lowerValue || this.upperValue != upperValue)) { + this.lowerValue = lowerValue; + this.upperValue = upperValue; + redraw(); + } + } + + /** + * Sets the 'upper selection', which is the upper receiver's value, to the input + * argument which must be greater than or equal to the current 'lower selection' + * and less or equal to the maximum. If either condition fails, no action is + * taken. + * + * @param value the new upper selection + * + * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * @see #getLowerValue() + * @see #getMaximum() + * @see #setSelection(int, int) + */ + public void setUpperValue(final int value) { + setSelection(lowerValue, value); + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ReflectionUtils.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ReflectionUtils.java new file mode 100644 index 0000000..93e97c6 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ReflectionUtils.java @@ -0,0 +1,48 @@ +package com.minres.scviewer.database.ui.swt.internal.slider; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ReflectionUtils { + /** + * Call a method using introspection (so ones can call a private or protected method) + * @param object object on which the method will be called + * @param methodName method name + * @param args arguments of this method (can be null) + * @return the value returned by this method (if this method returns a value) + */ + public static Object callMethod(final Object object, final String methodName, final Object... args) { + if (object == null) { + return null; + } + final Class[] array = new Class[args == null ? 0 : args.length]; + int index = 0; + if (args != null) { + for (final Object o : args) { + array[index++] = o == null ? Object.class : o.getClass(); + } + } + + return callMethodWithClassType(object, methodName, array, args); + } + + private static Object callMethodWithClassType(final Object object, final String methodName, final Class[] array, final Object... args) { + Class currentClass = object.getClass(); + Method method = null; + while (currentClass != null) { + try { + method = currentClass.getDeclaredMethod(methodName, array); + break; + } catch (final NoSuchMethodException nsme) { + currentClass = currentClass.getSuperclass(); + } + } + + try { + method.setAccessible(true); + return method.invoke(object, args); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + return null; + } + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/SelectionListenerUtil.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/SelectionListenerUtil.java new file mode 100644 index 0000000..273eca2 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/SelectionListenerUtil.java @@ -0,0 +1,74 @@ +package com.minres.scviewer.database.ui.swt.internal.slider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.TypedListener; + +public class SelectionListenerUtil { + /** + * Add a SelectionListener to a given Control + * + * @param control control on which the selection listener is added + * @param listener listener to add + */ + public static void addSelectionListener(final Control control, final SelectionListener listener) { + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + TypedListener typedListener = new TypedListener(listener); + control.addListener(SWT.Selection, typedListener); + } + + /** + * Remove a SelectionListener of a given Control + * + * @param control control on which the selection listener is removed + * @param listener listener to remove + */ + public static void removeSelectionListener(final Control control, final SelectionListener listener) { + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + final Listener[] listeners = control.getListeners(SWT.Selection); + for (Listener l : listeners) { + if (l instanceof TypedListener) { + TypedListener typedListener = (TypedListener) l; + if (typedListener.getEventListener() == listener) { + ReflectionUtils.callMethod(control, "removeListener", SWT.Selection, ((TypedListener) l).getEventListener()); + return; + } + } + } + } + + /** + * Fire the selection listeners of a given control + * + * @param control the control that fires the event + * @param sourceEvent mouse event + * @return true if the selection could be changed, false otherwise + */ + public static boolean fireSelectionListeners(final Control control, final Event sourceEvent) { + for (final Listener listener : control.getListeners(SWT.Selection)) { + final Event event = new Event(); + + event.button = sourceEvent==null?1:sourceEvent.button; + event.display = control.getDisplay(); + event.item = null; + event.widget = control; + event.data = sourceEvent == null ? null : sourceEvent.data; + event.time = sourceEvent == null ? 0 : sourceEvent.time; + event.x = sourceEvent == null ? 0 : sourceEvent.x; + event.y = sourceEvent == null ? 0 : sourceEvent.y; + event.type = SWT.Selection; + + listener.handleEvent(event); + if (!event.doit) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_left.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_left.png new file mode 100644 index 0000000000000000000000000000000000000000..96b446605ebf85c7142eb9ec096460ba2a9b330a GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~Unv^o$cHPZFwf!uL_esT;#rYmU(lg^$`c4sSKX3elF{r5}E*Evu=$5 literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_right.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_right.png new file mode 100644 index 0000000000000000000000000000000000000000..e809d370116b96a15258bb1e0551101f8bc2d74d GIT binary patch literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~f)_POe%sw|Iw383oe`7fwavx4 q6W*+l74C_@$!4K{RdLdXyWCG1nK!En^U45CW$<+Mb6Mw<&;$VPI%^*Q literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-drag.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-drag.png new file mode 100644 index 0000000000000000000000000000000000000000..2011d9b40b5cafb987a58f3af01a9333f3905fce GIT binary patch literal 1057 zcmeAS@N?(olHy`uVBq!ia0vp^f5hcz=sfi_-`FRQA=g;4G z^F4Xp-d-vn-?nmE0{``CV`Oh!E{#|)Y>t zcRv2Ubm`KMKmVS7`SakxgXq?!XKp?D_4i*$-Mnw#zHK^o73iH&Fd71shd_Aha}%H` zj3q&S!3+-1ZlnP@v7RoDAr-fh6Amz#g>5QO&^>hM)PaP&#H1DLSFc^UZjp+*-WgVr zNn1@!jV@ficqt%s+H`>jPm>(Q0w;((d6wcPI8o@)!vv@B!{<8E_^hR8#s0}r_&!7V ej`A^f5eA09t-?MpMSGru-0tb>=d#Wzp$Pyk5hcz=sfi_-`FRQRdO?fI8VrJbhi+Z*%hqsp)k# z8VUe~I14-?iy0XB4uLSEsD@VqP>?0v(btiIVPik{pF~y$24;o;pAgso|Np;u_qluR z(Z#Da+`4t^=g*%{-+ZcDdT8?Q>waaEC(l|iZSRej-~RZNOnmX-ThprJufF}=`rx~F z@x&PmmOXp+tY^!`nfq_P{{DBzqo3>U{Rpd@ef8>9oBEA!zW?3z_}8WfKhK{(|Mthf zZI6Dx`|)qrlRszAp8fj!-;MWwzWx4p`{SSQfBxP3^ykN)e~&)@dHUt=&p-d3fBk#u z(xsn&|GoV7_rZe)8FLO@c=-0$-+zfycYpi#ZO4VjK#z=q(GZ|k2pl}0t_(Dbu_VYZ zn8D%MjWi%9*3-o?q~ca`!U2XbF{1(n)iZ}q9Z1MZTe5!f;-w3ht5hcz=sfi_-`FRQXI+2kK-m@$_|Nzs=1fq^AF` zjj;_V#981GS*8o|0J?9FfcO&_=LFr|NsB(+qX-W zELpj7<*i${e*XOV`t|EMbLMQ?v?(_?cjnBQTefWZ{P}ZscJ{k>?-njx_~px&>({Sm zWo6BqH}BcAXRBAQ-nMPq&6_u`T)9$OT6*>B)q;Y8uV24jyLRpT`SWMbp8fUf*PAzQ ze*gac{{8z8A3l8i`0>)EOMm|S`Sj`2g9i^LOqg)@?%mGL&Trqooj!dU=*Uqp8UpkT zfpaT@Y=QPMmIV0)GdMiEkp|>Md%8G=RNP8VIKWV4b*Vr>^UR@B2No<{yN-p0i_6H! zD9I_tK{2zGH&is$&eg2YQH(J!PERaFFtU&_&o50xkke6)Pp!oCO;5(N4VxF5hcz=sfi_-`FRQKieMtHhuDU*ONas@BiL-|Ht;@-`gMm*nRqY@6#Xq&wn3%{$u~;@6#`T z9lrj3{`IfJx4$pH{mqzj$l=Z#$M1i4TzCw0)hHMZfdLEw{km1EKu&+{$d z*J+F)j$@L|k%jjdW3~osEsaKll_ASm?o=3KXti1^Kr4lE?vJ4?%XLMTk^KNRS(fGM zlPb&jTyJgk&N-^8A|Z-M+iea-@ZRISCxn1=j%KsTH%r9(>}T^$4FCWD07*qoM6N<$ Ef-c3JVgLXD literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl.png new file mode 100644 index 0000000000000000000000000000000000000000..558f9bd8c979be89c1625127ce3c88847c45428f GIT binary patch literal 386 zcmV-|0e$|7P)4f26vgrXz4OLqBLrMTNU@MMm93-=1QJ3NY^*IqAR(}wsQ5XoB?JU3KZC7>ogW|s z=IuD^%;ep7pG7tSC7$LqzjMekvu`|J<3CZEtyf>?uRj9yy}~!2mLK1Lmihe6`F%)B zE{vnHzyIpx+1cAq|02bqX$HCuwzr?ZI6Zy$*OTIf*d$^!77Jl(Ywz&ns8srfDiRHg*q=k3W0{>Oh7?bbcG8R4{|<>x#99J9|e*`X%6nc2QVbAtfOtNJ%hz zz;ya-H{j4lq0352U?wXlOeRVwE_AKZW?e0XWP&AS7?gm+uePG~KuSW+f|+7T==&Au zmx0a#W`boUo09$Zp+Mi&EInYRxZeOT$}m<0Tp0VBKG$Tw0bZ0+lyRsCRGBBUOD3fv gyWm;w`qA`?KQM~Ctzq%VNdN!<07*qoM6N<$f*$CpmjD0& literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl_lt.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..e37e735e502b7acb6e1d625a46287de40c4b4d20 GIT binary patch literal 366 zcmV-!0g?WRP)j!H;O&wemz9dZ^@hMa_yU~KfAPw6 M07*qoM6N<$f{SaUu>b%7 literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_lt.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_lt.png new file mode 100644 index 0000000000000000000000000000000000000000..237be7f3752ab84b25db8374f5847fe4adf72be8 GIT binary patch literal 345 zcmV-f0jBiG~f_AQAk{u*_uvWL=5?n#b6ay&&HjeY-yYF3# ziNk>L!r>O@I~UHyo1wgOcFaE$nc->tmOefKM+b>;d8OMd)5T)(d=Ls3BmLOzbhFv$ zd_I5q1BLUEZnI3YEYtORt!bLRb|H%@bzS3uIF6akW_PM;mdoV>;4BJtRUtqK0b>l) z>GW1r&1$u}x4OR|fcL)DWHPw{B8w_jRpC_e-V;J-q49WpZBZ!85&=Y{HAMsw!Gcni zCEu!u2qA>lG{!V7ilS(NZaPU4ECGt5pzb7p6-7~V;VaLnLclqPh_t)c>oq|BnN#@2 r=xQ(+UopbyE9pCRGGRBm-00000NkvXXu0mjf^cIxB literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-drag.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-drag.png new file mode 100644 index 0000000000000000000000000000000000000000..2d88c1afbd14dea934b22941e9beda11fe12abb4 GIT binary patch literal 1085 zcmeAS@N?(olHy`uVBq!ia0vp^AhsX}GmyOe_w02brB~t_QQ};bnpl#VpQjL#nVZT` zoS3VpU}&U}mtUr*U}Ruus9#HaCxutg6yO z_60y8&H|6fVg?4jLmgEw{G3~`Sa(Km+wlZtf^hJ$2Fy9;`BKUOZT0B{MI?S`q|r$l`}UsF57?c>4%ub zC!G?jrp;aW?Af#C#k*Tp9J>7cQ|g*a0SnLg=C)qFdQ~T>``W87S(|P~t-5;t{P`Pi zz9(z`#ezr6nbcf-AJ?|%H<{pkD0pMQ@(|M}(Dze{g^ef$0I z&d1-EE?xTZ=ik#We;zz|5Z$`;%&jNC{{9Q8oA>S8w@t^c0=+W|Mniz|5C~6wZUQug zu_VYZn8D%MjWi&q($mE;q~ezBvD-pU0TK-t_h0Jd3lYvTtG?hd$z;~rW54ag_g%X> z>7K@nxFaR{w)Tp;6L8^A*PJx*6cf*h7c{O#9lv;C zv3$#NgAeDGX0Lty)~38(VB*a?k(SxFC;b=qzC9~QvRC~L`~4fjKHbZ!3_#HaCxutoSRl zFa@9xXMsm#F#`kNArNL1)$nQn3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XN>+|Nj^7K6kG@ zx_H%wTeoig{Q2|gn@@F14^7^E-LGu&u)wjP}AAI*N zo;YK{vS-hp^=!E~bN|iP-~aA-^mE<4A7OQ~uU@@sQ@`=e_rJRy|JwB6=lS#J-~RZw z?a}XdKmP4{^5^W?vtNJzyYc?dx8MJ6fBf_P&%b-0{`~m!@6qQ!Prv;A`RCvBuYWIH zy7cq!zn9oVw+6e2tfeOw;3CY_U_V zu!Pw!{o&7f9C{4ftP2I)uebfYSNN8fJA3Q1f0MF=mMru=Zv*n1r>mdKI;Vst00{B; A;s5{u literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-normal.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-normal.png new file mode 100644 index 0000000000000000000000000000000000000000..4c5098ca95cb10882ccfe36902fac9a8de247103 GIT binary patch literal 1072 zcmeAS@N?(olHy`uVBq!ia0vp^AhsX}GmyOe_w02brB~t_QQ};bnpl#VpQjL#nVZT` zoS3VpU}&U}mtUr*U}Ruus9PU}#{lVd@EapicG@PhVH|+uS@tvK;Al z(N}>&oCO|{#S9F5hd`K7RKu$QD9DoT=wtDsIZQHipym|A=l`EyCrB|C>lyjvNJ}AwbU% zIJY9m7HA)1NswPKgTu2MX+Tbnr;B4q#Vyri(R@t?BCH3L!veY@RDwJ+4><<~^ZbsV zH|O?GsW%q`?=ysN;i+?XWdL(wZ7v`&G9Yemb}k??FflP8F*!OgHaamgAS*C2FfbqQ{ks4F00(qQ zO+^RW3k(tqC(w7(TL1t632;bRa{vGi!vFvd!vV){sAK>D00d`2O+f$vv5yP`8-0VU3{kYKMw+mZv00001bW%=J06^y0W&i*HY)M2x zRCwAg#?cl+KmbM2TP7hij3h~tM*jZ?bFB8$*5WPvBKi4?*-Li%V6tn+H%2dispose() method to - * release the operating system resources managed by cached objects when those - * objects and OS resources are no longer needed. - * - * This class may be freely distributed as part of any application or plugin. - *

- * - * @author scheglov_ke - * @author Dan Rubel - * @author Wim Jongman - */ -public class ResourceManager extends SWTResourceManager { - - /** - * The map where we store our images. - */ - private static Map m_descriptorImageMap = new HashMap(); - - /** - * Returns an {@link ImageDescriptor} stored in the file at the specified path - * relative to the specified class. - * - * @param clazz the {@link Class} relative to which to find the image - * descriptor. - * @param path the path to the image file. - * @return the {@link ImageDescriptor} stored in the file at the specified path. - */ - public static ImageDescriptor getImageDescriptor(Class clazz, String path) { - return ImageDescriptor.createFromFile(clazz, path); - } - - /** - * Returns an {@link ImageDescriptor} stored in the file at the specified path. - * - * @param path the path to the image file. - * @return the {@link ImageDescriptor} stored in the file at the specified path. - */ - public static ImageDescriptor getImageDescriptor(String path) { - try { - return ImageDescriptor.createFromURL(new File(path).toURI().toURL()); - } catch (MalformedURLException e) { - return null; - } - } - - /** - * Returns an {@link Image} based on the specified {@link ImageDescriptor}. - * - * @param descriptor the {@link ImageDescriptor} for the {@link Image}. - * @return the {@link Image} based on the specified {@link ImageDescriptor}. - */ - public static Image getImage(ImageDescriptor descriptor) { - if (descriptor == null) { - return null; - } - Image image = m_descriptorImageMap.get(descriptor); - if (image == null) { - image = descriptor.createImage(); - m_descriptorImageMap.put(descriptor, image); - } - return image; - } - - /** - * Maps images to decorated images. - */ - @SuppressWarnings("unchecked") - private static Map>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY]; - - /** - * Returns an {@link Image} composed of a base image decorated by another image. - * - * @param baseImage the base {@link Image} that should be decorated. - * @param decorator the {@link Image} to decorate the base image. - * @return {@link Image} The resulting decorated image. - */ - public static Image decorateImage(Image baseImage, Image decorator) { - return decorateImage(baseImage, decorator, BOTTOM_RIGHT); - } - - /** - * Returns an {@link Image} composed of a base image decorated by another image. - * - * @param baseImage - * the base {@link Image} that should be decorated. - * @param decorator - * the {@link Image} to decorate the base image. - * @param corner - * the corner to place decorator image. - * @return the resulting decorated {@link Image}. - */ - public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) { - if (corner <= 0 || corner >= LAST_CORNER_KEY) { - throw new IllegalArgumentException("Wrong decorate corner"); - } - Map> cornerDecoratedImageMap = m_decoratedImageMap[corner]; - if (cornerDecoratedImageMap == null) { - cornerDecoratedImageMap = new HashMap>(); - m_decoratedImageMap[corner] = cornerDecoratedImageMap; - } - Map decoratedMap = cornerDecoratedImageMap.get(baseImage); - if (decoratedMap == null) { - decoratedMap = new HashMap(); - cornerDecoratedImageMap.put(baseImage, decoratedMap); - } - // - Image result = decoratedMap.get(decorator); - if (result == null) { - final Rectangle bib = baseImage.getBounds(); - final Rectangle dib = decorator.getBounds(); - final Point baseImageSize = new Point(bib.width, bib.height); - CompositeImageDescriptor compositImageDesc = new CompositeImageDescriptor() { - @Override - protected void drawCompositeImage(int width, int height) { - drawImage(createCachedImageDataProvider(baseImage), 0, 0); - if (corner == TOP_LEFT) { - drawImage(getUnzoomedImageDataProvider(decorator.getImageData()) , 0, 0); - } else if (corner == TOP_RIGHT) { - drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), bib.width - dib.width, 0); - } else if (corner == BOTTOM_LEFT) { - drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), 0, bib.height - dib.height); - } else if (corner == BOTTOM_RIGHT) { - drawImage(getUnzoomedImageDataProvider(decorator.getImageData()), bib.width - dib.width, bib.height - dib.height); - } - } - @Override - protected Point getSize() { - return baseImageSize; - } - }; - // - result = compositImageDesc.createImage(); - decoratedMap.put(decorator, result); - } - return result; - } - - private static ImageDataProvider getUnzoomedImageDataProvider(ImageData imageData) { - return zoom -> zoom == 100 ? imageData : null; - } - - - /** - * Dispose all of the cached images. - */ - public static void disposeImages() { - SWTResourceManager.disposeImages(); - // dispose ImageDescriptor images - { - for (Iterator I = m_descriptorImageMap.values().iterator(); I.hasNext();) { - I.next().dispose(); - } - m_descriptorImageMap.clear(); - } - // dispose decorated images - for (int i = 0; i < m_decoratedImageMap.length; i++) { - Map> cornerDecoratedImageMap = m_decoratedImageMap[i]; - if (cornerDecoratedImageMap != null) { - for (Map decoratedMap : cornerDecoratedImageMap.values()) { - for (Image image : decoratedMap.values()) { - image.dispose(); - } - decoratedMap.clear(); - } - cornerDecoratedImageMap.clear(); - } - } - // dispose plugin images - { - for (Iterator I = m_URLImageMap.values().iterator(); I.hasNext();) { - I.next().dispose(); - } - m_URLImageMap.clear(); - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Plugin images support - // - //////////////////////////////////////////////////////////////////////////// - /** - * Maps URL to images. - */ - private static Map m_URLImageMap = new HashMap(); - - /** - * Provider for plugin resources, used by WindowBuilder at design time. - */ - public interface PluginResourceProvider { - URL getEntry(String symbolicName, String path); - } - - /** - * Instance of {@link PluginResourceProvider}, used by WindowBuilder at design - * time. - */ - private static PluginResourceProvider m_designTimePluginResourceProvider = null; - - /** - * Returns an {@link Image} based on a plugin and file path. - * - * @param plugin the plugin {@link Object} containing the image - * @param name the path to the image within the plugin - * @return the {@link Image} stored in the file at the specified path - * - * @deprecated Use {@link #getPluginImage(String, String)} instead. - */ - @Deprecated - public static Image getPluginImage(Object plugin, String name) { - try { - URL url = getPluginImageURL(plugin, name); - if (url != null) { - return getPluginImageFromUrl(url); - } - } catch (Throwable e) { - // Ignore any exceptions - } - return null; - } - - /** - * Returns an {@link Image} based on a {@link Bundle} and resource entry path. - * - * @param symbolicName the symbolic name of the {@link Bundle}. - * @param path the path of the resource entry. - * @return the {@link Image} stored in the file at the specified path. - */ - public static Image getPluginImage(String symbolicName, String path) { - try { - URL url = getPluginImageURL(symbolicName, path); - if (url != null) { - return getPluginImageFromUrl(url); - } - } catch (Throwable e) { - // Ignore any exceptions - } - return null; - } - - /** - * Returns an {@link Image} based on given {@link URL}. - */ - private static Image getPluginImageFromUrl(URL url) { - try { - try { - String key = url.toExternalForm(); - Image image = m_URLImageMap.get(key); - if (image == null) { - InputStream stream = url.openStream(); - try { - image = getImage(stream); - m_URLImageMap.put(key, image); - } finally { - stream.close(); - } - } - return image; - } catch (Throwable e) { - // Ignore any exceptions - } - } catch (Throwable e) { - // Ignore any exceptions - } - return null; - } - - /** - * Returns an {@link ImageDescriptor} based on a plugin and file path. - * - * @param plugin the plugin {@link Object} containing the image. - * @param name the path to th eimage within the plugin. - * @return the {@link ImageDescriptor} stored in the file at the specified path. - * - * @deprecated Use {@link #getPluginImageDescriptor(String, String)} instead. - */ - @Deprecated - public static ImageDescriptor getPluginImageDescriptor(Object plugin, String name) { - try { - try { - URL url = getPluginImageURL(plugin, name); - return ImageDescriptor.createFromURL(url); - } catch (Throwable e) { - // Ignore any exceptions - } - } catch (Throwable e) { - // Ignore any exceptions - } - return null; - } - - /** - * Returns an {@link ImageDescriptor} based on a {@link Bundle} and resource - * entry path. - * - * @param symbolicName the symbolic name of the {@link Bundle}. - * @param path the path of the resource entry. - * @return the {@link ImageDescriptor} based on a {@link Bundle} and resource - * entry path. - */ - public static ImageDescriptor getPluginImageDescriptor(String symbolicName, String path) { - try { - URL url = getPluginImageURL(symbolicName, path); - if (url != null) { - return ImageDescriptor.createFromURL(url); - } - } catch (Throwable e) { - // Ignore any exceptions - } - return null; - } - - /** - * Returns an {@link URL} based on a {@link Bundle} and resource entry path. - */ - private static URL getPluginImageURL(String symbolicName, String path) { - // try runtime plugins - { - Bundle bundle = Platform.getBundle(symbolicName); - if (bundle != null) { - return bundle.getEntry(path); - } - } - // try design time provider - if (m_designTimePluginResourceProvider != null) { - return m_designTimePluginResourceProvider.getEntry(symbolicName, path); - } - // no such resource - return null; - } - - /** - * Returns an {@link URL} based on a plugin and file path. - * - * @param plugin the plugin {@link Object} containing the file path. - * @param name the file path. - * @return the {@link URL} representing the file at the specified path. - * @throws Exception - */ - private static URL getPluginImageURL(Object plugin, String name) throws Exception { - // try to work with 'plugin' as with OSGI BundleContext - try { - Class BundleClass = Class.forName("org.osgi.framework.Bundle"); //$NON-NLS-1$ - Class BundleContextClass = Class.forName("org.osgi.framework.BundleContext"); //$NON-NLS-1$ - if (BundleContextClass.isAssignableFrom(plugin.getClass())) { - Method getBundleMethod = BundleContextClass.getMethod("getBundle", new Class[0]); //$NON-NLS-1$ - Object bundle = getBundleMethod.invoke(plugin, new Object[0]); - // - Class PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$ - Constructor pathConstructor = PathClass.getConstructor(new Class[] { String.class }); - Object path = pathConstructor.newInstance(new Object[] { name }); - // - Class IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$ - Class PlatformClass = Class.forName("org.eclipse.core.runtime.Platform"); //$NON-NLS-1$ - Method findMethod = PlatformClass.getMethod("find", new Class[] { BundleClass, IPathClass }); //$NON-NLS-1$ - return (URL) findMethod.invoke(null, new Object[] { bundle, path }); - } - } catch (Throwable e) { - // Ignore any exceptions - } - // else work with 'plugin' as with usual Eclipse plugin - { - Class PluginClass = Class.forName("org.eclipse.core.runtime.Plugin"); //$NON-NLS-1$ - if (PluginClass.isAssignableFrom(plugin.getClass())) { - // - Class PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$ - Constructor pathConstructor = PathClass.getConstructor(new Class[] { String.class }); - Object path = pathConstructor.newInstance(new Object[] { name }); - // - Class IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$ - Method findMethod = PluginClass.getMethod("find", new Class[] { IPathClass }); //$NON-NLS-1$ - return (URL) findMethod.invoke(plugin, new Object[] { path }); - } - } - return null; - } - - //////////////////////////////////////////////////////////////////////////// - // - // General - // - //////////////////////////////////////////////////////////////////////////// - /** - * Dispose of cached objects and their underlying OS resources. This should only - * be called when the cached objects are no longer needed (e.g. on application - * shutdown). - */ - public static void dispose() { - disposeColors(); - disposeFonts(); - disposeImages(); - } -} \ No newline at end of file From f9be6758e27a244781880e22b0547215760877be Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 3 Jan 2022 21:46:40 +0100 Subject: [PATCH 3/8] implement scrollbar adapter and first version of zooming scrollbar --- .../icons/bullet_left.png | Bin 307 -> 0 bytes .../icons/bullet_right.png | Bin 307 -> 0 bytes .../database/ui/swt/internal/IScrollBar.java | 37 ++++ .../internal/IWaveformScrollBarProvider.java | 7 + .../ui/swt/internal/ScrollBarAdapter.java | 83 ++++++++ .../ui/swt/internal/WaveformCanvas.java | 49 +++-- .../ui/swt/internal/WaveformView.java | 48 ++--- .../ui/swt/internal/ZoomingScrollbar.java | 108 ---------- .../ui/swt/internal/slider/ActionTimer.java | 35 ++++ .../ui/swt/internal/slider/ImageButton.java | 191 ++++++++++++------ .../ui/swt/internal/slider/RangeSlider.java | 60 +++--- .../swt/internal/slider/ZoomingScrollbar.java | 110 ++++++++++ .../ui/swt/internal/slider/arrow_left.png | Bin 0 -> 352 bytes .../swt/internal/slider/arrow_left_hover.png | Bin 0 -> 326 bytes .../internal/slider/arrow_left_pressed.png | Bin 0 -> 352 bytes .../ui/swt/internal/slider/arrow_right.png | Bin 0 -> 305 bytes .../swt/internal/slider/arrow_right_hover.png | Bin 0 -> 302 bytes .../internal/slider/arrow_right_pressed.png | Bin 0 -> 339 bytes .../ui/swt/internal/slider/bullet_left.png | Bin 307 -> 0 bytes .../ui/swt/internal/slider/bullet_right.png | Bin 307 -> 0 bytes .../ui/swt/internal/slider/marker_l.png | Bin 0 -> 374 bytes .../ui/swt/internal/slider/marker_l_bl.png | Bin 0 -> 353 bytes .../ui/swt/internal/slider/marker_l_bl_lt.png | Bin 0 -> 343 bytes .../ui/swt/internal/slider/marker_l_lt.png | Bin 0 -> 385 bytes 24 files changed, 468 insertions(+), 260 deletions(-) delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/icons/bullet_left.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/icons/bullet_right.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ActionTimer.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left_hover.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left_pressed.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right_hover.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right_pressed.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_left.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_right.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_bl.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_bl_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_lt.png diff --git a/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_left.png b/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_left.png deleted file mode 100644 index 96b446605ebf85c7142eb9ec096460ba2a9b330a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~Unv^o$cHPZFwf!uL_esT;#rYmU(lg^$`c4sSKX3elF{r5}E*Evu=$5 diff --git a/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_right.png b/plugins/com.minres.scviewer.database.ui.swt/icons/bullet_right.png deleted file mode 100644 index e809d370116b96a15258bb1e0551101f8bc2d74d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~f)_POe%sw|Iw383oe`7fwavx4 q6W*+l74C_@$!4K{RdLdXyWCG1nK!En^U45CW$<+Mb6Mw<&;$VPI%^*Q diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java new file mode 100644 index 0000000..9db93b6 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java @@ -0,0 +1,37 @@ +package com.minres.scviewer.database.ui.swt.internal; + +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; + +public interface IScrollBar { + + void setSelection(int i); + + int getSelection(); + + void setEnabled(boolean b); + + void setVisible(boolean b); + + void addSelectionListener(SelectionListener selectionListener); + + void setIncrement(int i); + + void setPageIncrement(int width); + + void setMinimum(int i); + + void setMaximum(int width); + + int getMaximum(); + + void setThumb(int clientWidthw); + + Point getSize(); + + int getStyle(); + + boolean isVisible(); + +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java new file mode 100644 index 0000000..11c8b97 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java @@ -0,0 +1,7 @@ +package com.minres.scviewer.database.ui.swt.internal; + +public interface IWaveformScrollBarProvider { + + IScrollBar getHorizontalSb(); + IScrollBar getVerticalSb(); +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java new file mode 100644 index 0000000..69e98e9 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java @@ -0,0 +1,83 @@ +package com.minres.scviewer.database.ui.swt.internal; + +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.ScrollBar; + +public class ScrollBarAdapter implements IScrollBar { + + ScrollBar delegate; + public ScrollBarAdapter(ScrollBar delegate) { + this.delegate=delegate; + } + + @Override + public void setSelection(int i) { + delegate.setSelection(i); + } + + @Override + public int getSelection() { + return delegate.getSelection(); + } + + @Override + public void setEnabled(boolean b) { + delegate.setEnabled(b); + } + + @Override + public void setVisible(boolean b) { + delegate.setVisible(b); + } + + @Override + public void addSelectionListener(SelectionListener selectionListener) { + delegate.addSelectionListener(selectionListener); } + + @Override + public void setIncrement(int i) { + delegate.setIncrement(i); + } + + @Override + public void setPageIncrement(int width) { + delegate.setPageIncrement(width); + } + + @Override + public void setMinimum(int i) { + delegate.setMinimum(i); + } + + @Override + public void setMaximum(int width) { + delegate.setMaximum(width); + } + + @Override + public int getMaximum() { + return delegate.getMaximum(); + } + + @Override + public void setThumb(int clientWidthw) { + delegate.setThumb(clientWidthw); + } + + @Override + public Point getSize() { + return delegate.getSize(); + } + + @Override + public int getStyle() { + return delegate.getStyle(); + } + + @Override + public boolean isVisible() { + return delegate.isVisible(); + } + +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java index cc8eb37..4add590 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java @@ -31,7 +31,6 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.ScrollBar; import com.google.common.collect.Lists; import com.minres.scviewer.database.EventEntry; @@ -81,6 +80,9 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ private List cursorPainters; + IScrollBar horizontal; + IScrollBar vertical; + HashMap wave2painterMap; /** * Constructor for ScrollableCanvas. @@ -90,8 +92,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ * @param style * the style of this control. */ - public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider) { - super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL); + public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider, IWaveformScrollBarProvider scrollbarProvider) { + super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND); this.styleProvider=styleProvider; addControlListener(new ControlAdapter() { /* resize listener. */ @Override @@ -106,6 +108,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ cursorPainters= new ArrayList<>(); wave2painterMap=new HashMap<>(); + horizontal = (style& SWT.H_SCROLL)==0?scrollbarProvider.getHorizontalSb() : new ScrollBarAdapter(getHorizontalBar()); + vertical = (style& SWT.V_SCROLL)==0?scrollbarProvider.getVerticalSb() : new ScrollBarAdapter(getVerticalBar()); initScrollBars(); // order is important: it is bottom to top trackAreaPainter=new TrackAreaPainter(this); @@ -149,12 +153,10 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void setOrigin(int x, int y) { checkWidget(); - ScrollBar hBar = getHorizontalBar(); - if(x<=0) hBar.setSelection(-x); - x = -hBar.getSelection(); - ScrollBar vBar = getVerticalBar(); - if(y<=0) vBar.setSelection(-y); - y = -vBar.getSelection(); + if(x<=0) horizontal.setSelection(-x); + x = -horizontal.getSelection(); + if(y<=0) vertical.setSelection(-y); + y = -vertical.getSelection(); origin.x = x; origin.y = y; syncScrollBars(); @@ -284,7 +286,6 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ /* Initialize the scrollbar and register listeners. */ private void initScrollBars() { - ScrollBar horizontal = getHorizontalBar(); horizontal.setEnabled(false); horizontal.setVisible(true); horizontal.addSelectionListener(new SelectionAdapter() { @@ -292,10 +293,9 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void widgetSelected(SelectionEvent event) { if (painterList.isEmpty()) return; - setOrigin(-((ScrollBar) event.widget).getSelection(), origin.y); + setOrigin(-horizontal.getSelection(), origin.y); } }); - ScrollBar vertical = getVerticalBar(); vertical.setEnabled(false); vertical.setVisible(true); vertical.addSelectionListener(new SelectionAdapter() { @@ -303,7 +303,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void widgetSelected(SelectionEvent event) { if (painterList.isEmpty()) return; - setOrigin(origin.x, -((ScrollBar) event.widget).getSelection()); + setOrigin(origin.x, -vertical.getSelection()); } }); } @@ -321,10 +321,9 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ int height = trackAreaPainter.getHeight(); // incl. Ruler long width = maxTime / scaleFactor; Rectangle clientArea=getClientArea(); - ScrollBar horizontal = getHorizontalBar(); - horizontal.setIncrement(getClientArea().width / 100); - horizontal.setPageIncrement(getClientArea().width); int clientWidthw = clientArea.width; + horizontal.setIncrement(clientWidthw / 100); + horizontal.setPageIncrement(clientWidthw/2); if (width > clientWidthw) { /* image is wider than client area */ horizontal.setMinimum(0); horizontal.setMaximum((int)width); @@ -338,10 +337,9 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ horizontal.setThumb(clientWidthw); horizontal.setSelection(-origin.x); - ScrollBar vertical = getVerticalBar(); - vertical.setIncrement(getClientArea().height / 100); - vertical.setPageIncrement(getClientArea().height); int clientHeighth = clientArea.height; + vertical.setIncrement(clientHeighth / 100); + vertical.setPageIncrement(clientHeighth/2); if (height > clientHeighth) { /* image is higher than client area */ vertical.setMinimum(0); vertical.setMaximum(height); @@ -437,8 +435,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ int lower = (int) (tx.getBeginTime() / scaleFactor); int higher = (int) (tx.getEndTime() / scaleFactor); Point size = getSize(); - size.x -= getVerticalBar().getSize().x + 2; - size.y -= getHorizontalBar().getSize().y; + size.x -= vertical.getSize().x + 2; + size.y -= horizontal.getSize().y; if (lower < -origin.x) { setOrigin(-lower, origin.y); } else if (higher > (size.x - origin.x)) { @@ -467,9 +465,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ if(te.waveform == waveform) { Point size = getSize(); size.y -=+rulerHeight; - ScrollBar sb = getHorizontalBar(); - if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible()) - size.y-= getHorizontalBar().getSize().y; + if((horizontal.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && horizontal.isVisible()) + size.y-= horizontal.getSize().y; int top = te.vOffset; int bottom = top + styleProvider.getTrackHeight(); if (top < -origin.y) { @@ -484,8 +481,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void reveal(long time) { int scaledTime = (int) (time / scaleFactor); Point size = getSize(); - size.x -= getVerticalBar().getSize().x + 2; - size.y -= getHorizontalBar().getSize().y; + size.x -= vertical.getSize().x + 2; + size.y -= horizontal.getSize().y; if (scaledTime < -origin.x) { setOrigin(-scaledTime+10, origin.y); } else if (scaledTime > (size.x - origin.x)) { diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 0deaa44..0eb64c3 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -95,6 +95,7 @@ import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.swt.internal.slider.ImageButton; import com.minres.scviewer.database.ui.swt.internal.slider.RangeSlider; +import com.minres.scviewer.database.ui.swt.internal.slider.ZoomingScrollbar; import com.minres.scviewer.database.ui.swt.sb.FlatScrollBar; public class WaveformView implements IWaveformView { @@ -343,40 +344,23 @@ public class WaveformView implements IWaveformView { gl_waveformPane.marginHeight = 0; waveformPane.setLayout(gl_waveformPane); - waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider); + IWaveformScrollBarProvider sbProvider = new IWaveformScrollBarProvider() { + @Override + public IScrollBar getVerticalSb() { + return null; + } + + @Override + public IScrollBar getHorizontalSb() { + ZoomingScrollbar timeSliderPane = new ZoomingScrollbar(waveformPane, SWT.NONE); + GridData gd_timeSliderPane = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); + timeSliderPane.setLayoutData(gd_timeSliderPane); + return timeSliderPane; + } + }; + waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider, sbProvider); waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - //Composite timeSliderPane = new WaveformSlider(waveformPane, SWT.NONE); - Composite timeSliderPane = new Composite(waveformPane, SWT.NONE); -// timeSliderPane.setBackground(SWTResourceManager.getColor(SWT.COLOR_RED)); - GridData gd_timeSliderPane = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); -// gd_timeSliderPane.heightHint = 22; - timeSliderPane.setLayoutData(gd_timeSliderPane); - GridLayout gl_timeSliderPane = new GridLayout(3, false); - gl_timeSliderPane.marginHeight=0; - gl_timeSliderPane.marginWidth=0; - gl_timeSliderPane.horizontalSpacing=0; - gl_timeSliderPane.verticalSpacing=0; - timeSliderPane.setLayout(gl_timeSliderPane); - ImageButton b1 = new ImageButton(timeSliderPane, SWT.NONE); - GridData gd_b1 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); - gd_b1.widthHint=18; - gd_b1.heightHint=18; - b1.setLayoutData(gd_b1); - b1.setImage(SWTResourceManager.getImage(RangeSlider.class, "bullet_left.png")); - - Composite timeSlider = new RangeSlider(timeSliderPane, SWT.ON|SWT.HIGH|SWT.SMOOTH|SWT.CONTROL); - GridData gd_timeSlide = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); - timeSlider.setLayoutData(gd_timeSlide); - - ImageButton b2 = new ImageButton(timeSliderPane, SWT.NONE); - GridData gd_b2 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); - gd_b2.widthHint=18; - gd_b2.heightHint=18; - b2.setLayoutData(gd_b2); - b2.setImage(SWTResourceManager.getImage(RangeSlider.class, "bullet_right.png")); - // create the name pane createTextPane(namePane, "Name"); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java deleted file mode 100644 index 96445f1..0000000 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ZoomingScrollbar.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.minres.scviewer.database.ui.swt.internal; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.layout.GridData; -import org.eclipse.wb.swt.ResourceManager; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.widgets.Slider; -import org.eclipse.wb.swt.SWTResourceManager; -import org.eclipse.swt.widgets.Scale; -import org.eclipse.jface.fieldassist.ControlDecoration; -import org.eclipse.swt.layout.FormLayout; -import org.eclipse.swt.layout.FillLayout; - -public class ZoomingScrollbar extends Composite { - - /** - * Create the composite. - * @param parent - * @param style - */ - public ZoomingScrollbar(Composite parent, int style) { - super(parent, SWT.BORDER | SWT.NO_FOCUS); - GridLayout gridLayout = new GridLayout(3, false); - gridLayout.horizontalSpacing = 0; - gridLayout.verticalSpacing = 0; - gridLayout.marginWidth = 0; - gridLayout.marginHeight = 0; - setLayout(gridLayout); - - Button scrlLeft = new Button(this, SWT.BORDER | SWT.FLAT | SWT.CENTER); - scrlLeft.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); - GridData gd_scrlLeft = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1); - gd_scrlLeft.heightHint = 16; - gd_scrlLeft.widthHint = 16; - scrlLeft.setLayoutData(gd_scrlLeft); - - Slider slider = new Slider(this, SWT.NONE); - slider.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); - GridData gd_canvas = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); - gd_canvas.heightHint = 16; - slider.setLayoutData(gd_canvas); - - Button scrlRight = new Button(this, SWT.BORDER | SWT.FLAT | SWT.CENTER); - scrlRight.setAlignment(SWT.CENTER); - GridData gd_scrlRight = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); - gd_scrlRight.heightHint = 16; - gd_scrlRight.widthHint = 16; - scrlRight.setLayoutData(gd_scrlRight); - - SashForm sashForm = new SashForm(this, SWT.NONE); - sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); - - Composite composite = new Composite(sashForm, SWT.NONE); - composite.setBackground(SWTResourceManager.getColor(SWT.COLOR_MAGENTA)); - composite.setLayout(null); - - Composite wavformPane = new Composite(sashForm, SWT.BORDER | SWT.NO_FOCUS); - wavformPane.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE)); - GridLayout gl_wavformPane = new GridLayout(1, false); - gl_wavformPane.verticalSpacing = 0; - gl_wavformPane.marginWidth = 0; - gl_wavformPane.marginHeight = 0; - wavformPane.setLayout(gl_wavformPane); - - Composite waveformCanvas = new Composite(wavformPane, SWT.NONE); - waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - Composite timeSlider = new Composite(wavformPane, SWT.BORDER | SWT.NO_FOCUS); - GridLayout gl_timeSlider = new GridLayout(3, false); - gl_timeSlider.marginWidth = 0; - gl_timeSlider.verticalSpacing = 0; - gl_timeSlider.marginHeight = 0; - gl_timeSlider.horizontalSpacing = 0; - timeSlider.setLayout(gl_timeSlider); - GridData gd_timeSlider = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); - gd_timeSlider.heightHint = 16; - timeSlider.setLayoutData(gd_timeSlider); - - Button buttonLeft = new Button(timeSlider, SWT.BORDER | SWT.FLAT | SWT.CENTER); - buttonLeft.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); - GridData gd_buttonLeft = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1); - gd_buttonLeft.widthHint = 10; - gd_buttonLeft.heightHint = 16; - buttonLeft.setLayoutData(gd_buttonLeft); - - Slider slider2 = new Slider(timeSlider, SWT.NONE); - slider2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1)); - - Button buttonRight = new Button(timeSlider, SWT.FLAT | SWT.CENTER); - buttonRight.setFont(SWTResourceManager.getFont("Sans", 5, SWT.NORMAL)); - GridData gd_buttonRight = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1); - gd_buttonRight.widthHint = 10; - gd_buttonRight.heightHint = 16; - buttonRight.setLayoutData(gd_buttonRight); - sashForm.setWeights(new int[] {1, 1}); - - } - - @Override - protected void checkSubclass() { - // Disable the check that prevents subclassing of SWT components - } -} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ActionTimer.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ActionTimer.java new file mode 100644 index 0000000..bacbe78 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ActionTimer.java @@ -0,0 +1,35 @@ +package com.minres.scviewer.database.ui.swt.internal.slider; + +import org.eclipse.swt.widgets.Display; + +public class ActionTimer implements Runnable { + + public static final int INITIAL_DELAY = 300; + public static final int FAST_DELAY = 50; + + private final Display display; + private final TimerAction timerAction; + + public interface TimerAction extends Runnable { + boolean isEnabled(); + } + + public ActionTimer( TimerAction timerAction, Display display ) { + this.display = display; + this.timerAction = timerAction; + } + + public void activate() { + if( timerAction.isEnabled() ) { + display.timerExec( INITIAL_DELAY, this ); + } + } + + @Override + public void run() { + if( timerAction.isEnabled() ) { + timerAction.run(); + display.timerExec( FAST_DELAY, this ); + } + } +} \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java index 21483d6..3c3ca72 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java @@ -1,111 +1,100 @@ package com.minres.scviewer.database.ui.swt.internal.slider; import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; public class ImageButton extends Composite { - private Color textColor; - private Image image; - private Image grayImage; - private ImageData imageData; - private String text = ""; + private Image hoverImage; + private Image normalImage; + private Image pressedImage; private int width; private int height; private boolean hover; + private boolean pressed; + private boolean autoFire; + private ActionTimer actionTimer; + private ActionTimer.TimerAction timerAction; - public ImageButton(Composite parent, int style) - { + public ImageButton(Composite parent, int style) { super(parent, style); - - textColor = Display.getDefault().getSystemColor(SWT.COLOR_WHITE); - - /* Add dispose listener for the image */ + + timerAction = new ActionTimer.TimerAction() { + @Override + public void run() { + notifyListeners(); + } + @Override + public boolean isEnabled() { + return pressed; + } + }; + actionTimer = new ActionTimer(timerAction, this.getDisplay() ); + addListener(SWT.Dispose, event -> { - if (image != null) - image.dispose(); + if (hoverImage != null) hoverImage.dispose(); + if (normalImage != null) normalImage.dispose(); + if (pressedImage != null) pressedImage.dispose(); }); - /* Add custom paint listener that paints the stars */ addListener(SWT.Paint, event -> { - paintControl(event); + paintControl(event); }); - /* Listen for click events */ - addListener(SWT.MouseDown, event -> { - System.out.println("Click"); - }); addListener(SWT.MouseDown, event -> { + pressed=true; + notifyListeners(); + if(autoFire) actionTimer.activate(); + redraw(); }); addListener(SWT.MouseUp, event -> { + pressed=false; + redraw(); }); addListener(SWT.MouseMove, event -> { - hover=false; + Point sz = ((ImageButton)event.widget).getSize(); + final boolean within_x = event.x>0 && event.x0 && event.y { - }); - - addListener(SWT.MouseHover, event -> { - hover=true; - redraw(); - }); - - addListener(SWT.MouseDoubleClick, event -> { - }); } private void paintControl(Event event) { GC gc = event.gc; - if (image != null) - { -// gc.drawImage(image, 1, 1); -// if(hover) { -// Rectangle rect = image.getBounds (); -// Transform tr = new Transform (event.display); -// tr.setElements (1, 0, 0, -1, 1, 2*(1+rect.height)); -// gc.setTransform (tr); -// gc.drawImage (image, 1, 1); -// gc.setTransform (null); -// } - if(hover) { - gc.drawImage(image, 1, 1); + if (hoverImage != null) { + if(pressed) + gc.drawImage(pressedImage, 1, 1); + else if(hover) { + gc.drawImage(hoverImage, 1, 1); } else { - gc.drawImage(grayImage, 1, 1); + gc.drawImage(normalImage, 1, 1); } - Point textSize = gc.textExtent(text); - gc.setForeground(textColor); - gc.drawText(text, (width - textSize.x) / 2 + 1, (height - textSize.y) / 2 + 1, true); } } - public void setImage(Image img) + public void setImage(Image[] imgs) { - image = new Image(Display.getDefault(), img, SWT.IMAGE_COPY); - grayImage = new Image(Display.getDefault(),img,SWT.IMAGE_GRAY); - width = img.getBounds().width; - height = img.getBounds().height; - imageData = img.getImageData(); - redraw(); - } - - public void setText(String text) - { - this.text = text; + Display d = Display.getDefault(); + hoverImage = new Image(d, imgs[0], SWT.IMAGE_COPY); + normalImage = imgs.length>1? + new Image(d, imgs[1], SWT.IMAGE_COPY): + new Image(d,imgs[0],SWT.IMAGE_GRAY); + pressedImage = imgs.length>2? + new Image(d, imgs[2], SWT.IMAGE_COPY): + new Image(d,imgs[0],SWT.IMAGE_DISABLE); + width = imgs[0].getBounds().width; + height = imgs[0].getBounds().height; redraw(); } @@ -125,5 +114,77 @@ public class ImageButton extends Composite /* Return computed dimensions plus border */ return new Point(overallWidth + 2, overallHeight + 2); } + /** + * Adds the listener to the collection of listeners who will be notified when + * the user changes the receiver's value, by sending it one of the messages + * defined in the SelectionListener interface. + *

+ * widgetSelected is called when the user changes the receiver's + * value. widgetDefaultSelected is not called. + *

+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see SelectionListener + * @see #removeSelectionListener + */ + public void addSelectionListener(final SelectionListener listener) { + checkWidget(); + SelectionListenerUtil.addSelectionListener(this, listener); + } + + /** + * Removes the listener from the collection of listeners who will be notified + * when the user changes the receiver's value. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException + *
    + *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • + *
+ * @exception SWTException + *
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been + * disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the + * thread that created the receiver
  • + *
+ * + * @see SelectionListener + * @see #addSelectionListener + */ + public void removeSelectionListener(final SelectionListener listener) { + checkWidget(); + SelectionListenerUtil.removeSelectionListener(this, listener); + } + + private void notifyListeners() { + Event e = new Event(); + e.widget=this; + e.type=SWT.Selection; + SelectionListenerUtil.fireSelectionListeners(this,e); + } + + public boolean isAutoFire() { + return autoFire; + } + + public void setAutoFire(boolean autoFire) { + this.autoFire = autoFire; + } + } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java index d146b53..0b78cd4 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java @@ -59,7 +59,7 @@ public class RangeSlider extends Canvas { private int maximum; private int lowerValue; private int upperValue; - private final Image slider, sliderHover, sliderDrag, sliderSelected; + private final Image[] slider, sliderHover, sliderDrag, sliderSelected; private final Image vSlider, vSliderHover, vSliderDrag, vSliderSelected; private int orientation; private int increment; @@ -114,10 +114,18 @@ public class RangeSlider extends Canvas { maximum = upperValue = 100; increment = 1; pageIncrement = 10; - slider = SWTResourceManager.getImage(this.getClass(), "marker_r.png"); - sliderHover = SWTResourceManager.getImage(this.getClass(), "marker_r_lt.png"); - sliderDrag = SWTResourceManager.getImage(this.getClass(), "marker_r_bl.png"); - sliderSelected = SWTResourceManager.getImage(this.getClass(), "marker_r_bl_lt.png"); + slider = new Image[] { + SWTResourceManager.getImage(this.getClass(), "marker_l.png"), + SWTResourceManager.getImage(this.getClass(), "marker_r.png")}; + sliderHover = new Image[] { + SWTResourceManager.getImage(this.getClass(), "marker_l_lt.png"), + SWTResourceManager.getImage(this.getClass(), "marker_r_lt.png")}; + sliderDrag = new Image[] { + SWTResourceManager.getImage(this.getClass(), "marker_l_bl.png"), + SWTResourceManager.getImage(this.getClass(), "marker_r_bl.png")}; + sliderSelected = new Image[] { + SWTResourceManager.getImage(this.getClass(), "marker_l_bl_lt.png"), + SWTResourceManager.getImage(this.getClass(), "marker_r_bl_lt.png")}; vSlider = SWTResourceManager.getImage(this.getClass(), "h-slider-normal.png"); vSliderHover = SWTResourceManager.getImage(this.getClass(), "h-slider-hover.png"); @@ -371,7 +379,7 @@ public class RangeSlider extends Canvas { if (coordLower == null) { return; } - final Image img = orientation == SWT.HORIZONTAL ? slider : vSlider; + final Image img = orientation == SWT.HORIZONTAL ? slider[0] : vSlider; final int x = e.x, y = e.y; lowerHover = x >= coordLower.x && x <= coordLower.x + img.getBounds().width && y >= coordLower.y && y <= coordLower.y + img.getBounds().height; upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && // @@ -621,7 +629,6 @@ public class RangeSlider extends Canvas { */ private void drawHorizontalRangeSlider(final GC gc) { drawBackgroundHorizontal(gc); - drawBarsHorizontal(gc); if (lowerHover || (selectedElement & LOWER) != 0) { coordUpper = drawHorizontalKnob(gc, upperValue, true); coordLower = drawHorizontalKnob(gc, lowerValue, false); @@ -640,6 +647,7 @@ public class RangeSlider extends Canvas { final Rectangle clientArea = getClientArea(); gc.setBackground(getBackground()); + //gc.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE));//getBackground()); gc.fillRectangle(clientArea); if (isEnabled()) { @@ -647,7 +655,7 @@ public class RangeSlider extends Canvas { } else { gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); } - gc.drawRoundRectangle(minHeight/3+imgWidth, minHeight/3, clientArea.width - 2*(minHeight/3+imgWidth), clientArea.height - 2*minHeight/3+3, 3, 3); + gc.drawRoundRectangle(imgWidth, minHeight/3, clientArea.width - 2*imgWidth, clientArea.height - 2*minHeight/3, 3, 3); final float pixelSize = computePixelSizeForHorizontalSlider(); final int startX = (int) (pixelSize * lowerValue); @@ -657,7 +665,7 @@ public class RangeSlider extends Canvas { } else { gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); } - gc.fillRectangle(minHeight/3+3 + startX, minHeight/3, endX - startX - 3, clientArea.height - 2*minHeight/3+3); + gc.fillRectangle(imgWidth+startX, minHeight/3, endX - startX, clientArea.height - 2*minHeight/3); } @@ -665,15 +673,7 @@ public class RangeSlider extends Canvas { * @return how many pixels corresponds to 1 point of value */ private float computePixelSizeForHorizontalSlider() { - return (getClientArea().width - 20f) / (maximum - minimum); - } - - /** - * Draw the bars - * - * @param gc graphic context - */ - private void drawBarsHorizontal(final GC gc) { + return (getClientArea().width - 2.0f*imgWidth) / (maximum - minimum); } /** @@ -687,33 +687,36 @@ public class RangeSlider extends Canvas { */ private Point drawHorizontalKnob(final GC gc, final int value, final boolean upper) { final float pixelSize = computePixelSizeForHorizontalSlider(); - final int x = (int) (pixelSize * value); + int x = (int) (pixelSize * value); + final int idx = upper?1:0; Image image; if (upper) { if (upperHover) { - image = dragInProgress || (selectedElement & UPPER) != 0 ? sliderDrag : sliderHover; + image = dragInProgress || (selectedElement & UPPER) != 0 ? sliderDrag[idx] : sliderHover[idx]; } else if ((selectedElement & UPPER) != 0 && !lowerHover) { - image = hasFocus ? sliderSelected : sliderHover; + image = hasFocus ? sliderSelected[idx] : sliderHover[idx]; } else { - image = slider; + image = slider[idx]; } } else { if (lowerHover) { - image = dragInProgress || (selectedElement & LOWER) != 0 ? sliderDrag : sliderHover; + image = dragInProgress || (selectedElement & LOWER) != 0 ? sliderDrag[idx] : sliderHover[idx]; } else if ((selectedElement & LOWER) != 0 && !upperHover) { - image = hasFocus ? sliderSelected : sliderHover; + image = hasFocus ? sliderSelected[idx] : sliderHover[idx]; } else { - image = slider; + image = slider[idx]; } } + if(upper) + x+=slider[idx].getBounds().width; if (isEnabled()) { - gc.drawImage(image, x + 5, getClientArea().height / 2 - slider.getBounds().height / 2); + gc.drawImage(image, x, getClientArea().height / 2 - slider[idx].getBounds().height / 2); } else { final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE); - gc.drawImage(temp, x + 5, getClientArea().height / 2 - slider.getBounds().height / 2); + gc.drawImage(temp, x, getClientArea().height / 2 - slider[idx].getBounds().height / 2); temp.dispose(); } - return new Point(x + 5, getClientArea().height / 2 - slider.getBounds().height / 2); + return new Point(x, getClientArea().height / 2 - slider[idx].getBounds().height / 2); } /** @@ -775,7 +778,6 @@ public class RangeSlider extends Canvas { * @param gc graphic context */ private void drawBarsVertical(final GC gc) { - final Rectangle clientArea = getClientArea(); if (isEnabled()) { gc.setForeground(getForeground()); } else { diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java new file mode 100644 index 0000000..077da38 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java @@ -0,0 +1,110 @@ +package com.minres.scviewer.database.ui.swt.internal.slider; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +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.wb.swt.SWTResourceManager; + +import com.minres.scviewer.database.ui.swt.internal.IScrollBar; + +public class ZoomingScrollbar extends Composite implements IScrollBar { + RangeSlider timeSlider; + /** + * Create the composite. + * @param parent + * @param style + */ + public ZoomingScrollbar(Composite parent, int style) { + super(parent, SWT.NO_FOCUS); + GridLayout gridLayout = new GridLayout(3, false); + gridLayout.horizontalSpacing = 0; + gridLayout.verticalSpacing = 0; + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + setLayout(gridLayout); + //setBackground(SWTResourceManager.getColor(SWT.COLOR_RED)); + + ImageButton b1 = new ImageButton(this, SWT.NONE); + GridData gd_b1 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_b1.widthHint=14; + gd_b1.heightHint=18; + b1.setLayoutData(gd_b1); + b1.setImage(new Image[] { + SWTResourceManager.getImage(this.getClass(), "arrow_left_hover.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_left.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_left_pressed.png")}); + b1.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + int[] value = timeSlider.getSelection(); + int diff = value[1]-value[0]; + int newLow = Math.max(0, value[0]-Math.max(1, diff/10)); + timeSlider.setSelection(newLow, newLow+diff); + } + }); + timeSlider = new RangeSlider(this, /*SWT.ON|*/SWT.HIGH|SWT.SMOOTH|SWT.CONTROL); + GridData gd_timeSlide = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); + timeSlider.setLayoutData(gd_timeSlide); + + ImageButton b2 = new ImageButton(this, SWT.NONE); + GridData gd_b2 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_b2.widthHint=18; + gd_b2.heightHint=18; + b2.setLayoutData(gd_b2); + b2.setImage(new Image[] { + SWTResourceManager.getImage(this.getClass(), "arrow_right_hover.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_right.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_right_pressed.png")}); + b2.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + int[] value = timeSlider.getSelection(); + int diff = value[1]-value[0]; + int newHigh = Math.min(timeSlider.getMaximum(), value[1] + diff/10); + timeSlider.setSelection(newHigh-diff, newHigh); + } + }); + + } + @Override + public void setSelection(int i) { + timeSlider.setLowerValue(i); + } + @Override + public int getSelection() { + return timeSlider.getLowerValue(); + } + @Override + public void addSelectionListener(SelectionListener selectionListener) { + timeSlider.addSelectionListener(selectionListener); + } + @Override + public void setIncrement(int value) { + timeSlider.setIncrement(value); + } + @Override + public void setPageIncrement(int value) { + timeSlider.setPageIncrement(value); + } + @Override + public void setMinimum(int value) { + timeSlider.setMinimum(value); + } + @Override + public void setMaximum(int value) { + timeSlider.setMaximum(value); + } + @Override + public int getMaximum() { + return timeSlider.getMaximum(); + } + @Override + public void setThumb(int w) { + timeSlider.setUpperValue(timeSlider.getLowerValue()+w); + } +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left.png new file mode 100644 index 0000000000000000000000000000000000000000..61e7214d2faff98722828e1f5f2c035e3203d065 GIT binary patch literal 352 zcmV-m0iXVfP)U?`jf5Ktuuyrcx|oW1lilV6m^1Huw@LeS?5cA+a;1s34jY?%us)v57y? z;5slc#dppbh7mQZIqIgsg=&Bf$Pi}CeNYKj7#N>|P1o|og98PF04gdj`R3Xpi)Y@I2f~#G1z0c?1ZzQa)Xjj)*i%}b zdd!0Yuxb~8V32=FSeJsK2)2S%RI}DA8Tc?=-Xz2JL@yk15QV=P2^S`=Tq!XjcgRUnsL`cNE+GiHgsQQ8h=yg@4~)>^%^IP(J*Q`Zo%r`UE0$SjRoCV!q|F$ Y12q$jIyPEPMgRZ+07*qoM6N<$f>Y{;c>n+a literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left_pressed.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_left_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..61e7214d2faff98722828e1f5f2c035e3203d065 GIT binary patch literal 352 zcmV-m0iXVfP)U?`jf5Ktuuyrcx|oW1lilV6m^1Huw@LeS?5cA+a;1s34jY?%us)v57y? z;5slc#dppbh7mQZIqIgsg=&Bf$Pi}CeNYKj7#N>|P1o|og98PF04gdj`R3Xpi)Y@I2f~#G1z0c?1ZzQa)Xjj)*i%}b zdd!0Yuxb~8V32=FSeJsK2)2S%RI}DA8Tc?=-Xz2JL@ykD+n%jp9Z{CdnKIJb^?>ycDDyDYj)3Ai(0? z`%c1@{>zoV;K8H72I0q*e(OrF_Xie8|DlCB4#44_rU3RT^q&hgFI$+`6a!iVjQFm^ zwH7?x))YWmL4rUq%t3rpwU_H!S}9mkS|9)sYz4NWK&M(3K*Deh8bcZYfoBw9&^Ajf z1?hk;DUu}#S+&1!SVCT-vlJY{?KvEQ3fR^A(=iW>!};9-a0GThRqs!65KNjBKCcj` zt>fRCgk~hzW$SdnKx&}B-FhkX^R52}D&Tvrb$osSCO3)ASR|!700000NkvXXu0mjf DTA6)L literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right_hover.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..890472f01105135d9629f870fc66ed405f43a850 GIT binary patch literal 302 zcmV+}0nz@6P)NklV4e5Jle%ASIh34T`kV7E$hmR^kZhxRjeMauRNV#0_Y$=cn*SVS%ujYHaKMH)ERA zeKx6U`DZz>!Pqyc>zma1Jm6S<_f{(skmhU-pcf~9EIeMVpR?7=5=bJ}PI>cIi@$9Z z$cATwBD8{7yX%R&Hb+1Pir_r8J zil9`Bl@Tm}es@^b9aJCkH3WzN24HvE9*)&;t_H?b3RnQ*2<(92v^~U+L1bNw1;jM< z@>?f{afF-HDWDM$f$pc?7>LKI*T4XLJxaZ-Z@eFjf<*4(i~s-t07*qoM6N<$g7{{E AkpKVy literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right_pressed.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/arrow_right_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..b37d47d064292a3c62834231f6a71daa6148c913 GIT binary patch literal 339 zcmV-Z0j&OsP)Z5JX?~%zD=(Ac0n_Laya%GN1?C7j@Y$>e3D|K%_#9fYE<6L*QNE$1=L~|D&~H4&H@y zCj49#*>0Kv@*Kzox$qN6S7v^yKWXiu)3$fOJHn43T^h}`RTSGagXQ4TC_GcEmE!9r zSh`rzdJ!##BCu+Q&}vG6);mN1GC}4Lg$Gb3+=RV5_ShtSG6n|o;dBxKJa-5Sdl0x2 zUK;GxCpZIOJReTenh;yO2N7lodrC(tF>ZFk6omZ@*QQ@0I(W(j*vTX)^{H6jfj l9@5^_pM){a-M-Y#`UZ^Odncvs-K78k002ovPDHLkV1muKk8uD1 literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_left.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_left.png deleted file mode 100644 index 96b446605ebf85c7142eb9ec096460ba2a9b330a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~Unv^o$cHPZFwf!uL_esT;#rYmU(lg^$`c4sSKX3elF{r5}E*Evu=$5 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_right.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/bullet_right.png deleted file mode 100644 index e809d370116b96a15258bb1e0551101f8bc2d74d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^E07j0XYijYA3s;uwp&oQ znNhToK@yClD;eag8RTmj6v0TlnK603VfJEk)p`cgc6Qf(ak*;d!0C$NGc=-SYsM_F ziC^fPwAc-(CUw4H+ER~f)_POe%sw|Iw383oe`7fwavx4 q6W*+l74C_@$!4K{RdLdXyWCG1nK!En^U45CW$<+Mb6Mw<&;$VPI%^*Q diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l.png new file mode 100644 index 0000000000000000000000000000000000000000..b6a942d679bc08c038208231f410de3c9f1f3a3e GIT binary patch literal 374 zcmV-+0g3*JP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Sie)K~yMHb&*R- z#6S>+E05ktz@6JhglrADKrRpv(F=Hlge2xPZez=uAFa!f0=XsH`v?r(~H3`tvNplmgo8AcsR)E#*=ex36^EqwkQhu zvER$-`c|%2ury6y!!Udt#}R}OASVeLU`di}f*^PphJl)*Z2{yjz~VUG`o4ePbse;- z(KHR6fDTa$+a1*AM}H-&2AR3h%T=uh0(b zNy?S}bXWX<30yEe*Ho#Fw-k#{tjtz_x8LO%p83B3&4U`tu|F0OYsu Ub#Xn<4gdfE07*qoM6N<$f(vSwr~m)} literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_bl.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_bl.png new file mode 100644 index 0000000000000000000000000000000000000000..8ae0c09ee63b257b7810abfa1720572b335c2f9d GIT binary patch literal 353 zcmV-n0iOPeP)j6k-xI4^0QUsaVJK80n@3UHw_PMB<{5CKY;PrFXnUZ zLx5dnwQqbcyuSM7WWpT~RN1Tr$GihZBflCBxm~YGrO>Kkn}T5={k~s6J#+KEB9(%v zLe7Lu!DvAS1Fql3WK}2y&$;uqY+uwhaW*4u!>Z)PHbXelDN3tfesAR-8Ezy(;?*w~5NaTTf3r3oPbT{DP)8gv2_khUdM z710b=0~Op1iV}7&>Y5~i_ZC+Jv>(~FgldVXQu@$U@Hik+K$@0V*IPiOHz+QKPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0TxL_K~yMHb&g9) z#6S>+D-*JlQ34SHAp`0G#$}F>Wke-w50TehT&m+0Jc1|4GK+wV0m=KFwB2PoWCRO7 z(w+LM{)YeR6E4q2VK;2%``?m2yr*YjcOlOAlahiUc>9WDGTq#g`QK8K@B4=+ipclz zNT%!ki6D8N_a25JiRm@m>@Zh^J-bvgCGddG!4>H zfCg-6^I)3h{Wy+L*Y$66-ayy}!!YjpzF#Jp#6^r4h5^d5gsQ3#-eg~lVAJa+KQ~OE z# Date: Wed, 5 Jan 2022 21:51:57 +0100 Subject: [PATCH 4/8] checkpoint development --- .../database/ui/swt/DatabaseUiPlugin.java | 2 + .../database/ui/swt/internal/IScrollBar.java | 37 ---- .../internal/IWaveformScrollBarProvider.java | 7 - .../ui/swt/internal/ScrollBarAdapter.java | 83 --------- .../ui/swt/internal/TrackAreaPainter.java | 15 +- .../ui/swt/internal/WaveformCanvas.java | 175 ++++++++++-------- .../ui/swt/internal/WaveformSlider.java | 95 ---------- .../ui/swt/internal/WaveformView.java | 22 +-- .../ui/swt/internal/slider/ImageButton.java | 43 ++--- .../ui/swt/internal/slider/RangeSlider.java | 50 ++--- ...gScrollbar.java => TimeZoomScrollbar.java} | 109 ++++++----- 11 files changed, 219 insertions(+), 419 deletions(-) delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformSlider.java rename plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/{ZoomingScrollbar.java => TimeZoomScrollbar.java} (50%) diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/DatabaseUiPlugin.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/DatabaseUiPlugin.java index 98aa447..0d8b315 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/DatabaseUiPlugin.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/DatabaseUiPlugin.java @@ -13,6 +13,7 @@ package com.minres.scviewer.database.ui.swt; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; +import org.eclipse.wb.swt.SWTResourceManager; import org.osgi.framework.BundleContext; public class DatabaseUiPlugin extends Plugin { @@ -24,6 +25,7 @@ public class DatabaseUiPlugin extends Plugin { @Override public void stop(BundleContext context) throws Exception { + SWTResourceManager.dispose(); getLog().log(new Status(IStatus.OK, "org.eclipse.e4.core", "Stopping org.eclipse.e4.core bundle...")); } } \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java deleted file mode 100644 index 9db93b6..0000000 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IScrollBar.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.minres.scviewer.database.ui.swt.internal; - -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; - -public interface IScrollBar { - - void setSelection(int i); - - int getSelection(); - - void setEnabled(boolean b); - - void setVisible(boolean b); - - void addSelectionListener(SelectionListener selectionListener); - - void setIncrement(int i); - - void setPageIncrement(int width); - - void setMinimum(int i); - - void setMaximum(int width); - - int getMaximum(); - - void setThumb(int clientWidthw); - - Point getSize(); - - int getStyle(); - - boolean isVisible(); - -} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java deleted file mode 100644 index 11c8b97..0000000 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/IWaveformScrollBarProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.minres.scviewer.database.ui.swt.internal; - -public interface IWaveformScrollBarProvider { - - IScrollBar getHorizontalSb(); - IScrollBar getVerticalSb(); -} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java deleted file mode 100644 index 69e98e9..0000000 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ScrollBarAdapter.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.minres.scviewer.database.ui.swt.internal; - -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.ScrollBar; - -public class ScrollBarAdapter implements IScrollBar { - - ScrollBar delegate; - public ScrollBarAdapter(ScrollBar delegate) { - this.delegate=delegate; - } - - @Override - public void setSelection(int i) { - delegate.setSelection(i); - } - - @Override - public int getSelection() { - return delegate.getSelection(); - } - - @Override - public void setEnabled(boolean b) { - delegate.setEnabled(b); - } - - @Override - public void setVisible(boolean b) { - delegate.setVisible(b); - } - - @Override - public void addSelectionListener(SelectionListener selectionListener) { - delegate.addSelectionListener(selectionListener); } - - @Override - public void setIncrement(int i) { - delegate.setIncrement(i); - } - - @Override - public void setPageIncrement(int width) { - delegate.setPageIncrement(width); - } - - @Override - public void setMinimum(int i) { - delegate.setMinimum(i); - } - - @Override - public void setMaximum(int width) { - delegate.setMaximum(width); - } - - @Override - public int getMaximum() { - return delegate.getMaximum(); - } - - @Override - public void setThumb(int clientWidthw) { - delegate.setThumb(clientWidthw); - } - - @Override - public Point getSize() { - return delegate.getSize(); - } - - @Override - public int getStyle() { - return delegate.getStyle(); - } - - @Override - public boolean isVisible() { - return delegate.isVisible(); - } - -} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/TrackAreaPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/TrackAreaPainter.java index 90326e3..300c7be 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/TrackAreaPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/TrackAreaPainter.java @@ -19,7 +19,7 @@ import org.eclipse.swt.graphics.Rectangle; import com.minres.scviewer.database.ui.WaveformColors; public class TrackAreaPainter implements IPainter { - + /** * */ @@ -35,14 +35,15 @@ public class TrackAreaPainter implements IPainter { } public void paintArea(Projection proj, Rectangle a) { - Rectangle area = proj.unProject(new Rectangle(a.x, a.y+waveCanvas.rulerHeight, a.width, a.height-waveCanvas.rulerHeight)); - proj.setBackground(this.waveCanvas.styleProvider.getColor(WaveformColors.TRACK_BG_EVEN)); - proj.setFillRule(SWT.FILL_EVEN_ODD); - proj.fillRectangle(area); + Rectangle area = proj.unProject(new Rectangle(a.x, a.y+waveCanvas.rulerHeight, a.width, a.height-waveCanvas.rulerHeight)); + proj.setBackground(this.waveCanvas.styleProvider.getColor(WaveformColors.TRACK_BG_EVEN)); + proj.setFillRule(SWT.FILL_EVEN_ODD); + proj.fillRectangle(area); if(trackVerticalOffset.size()>0){ Integer firstKey=trackVerticalOffset.floorKey(area.y); if(firstKey==null) firstKey=trackVerticalOffset.firstKey(); Integer lastKey = trackVerticalOffset.floorKey(area.y+area.height); + //if(lastKey==null) lastKey= trackVerticalOffset.lastKey(); Rectangle subArea = new Rectangle(area.x, 0, area.width, 0); if(lastKey.equals(firstKey)){ subArea.y=firstKey; @@ -61,9 +62,9 @@ public class TrackAreaPainter implements IPainter { public void addTrackPainter(IWaveformPainter trackPainter){ trackVerticalOffset.put(trackPainter.getVerticalOffset()+waveCanvas.rulerHeight, trackPainter); - + } - + public int getHeight(){ if(trackVerticalOffset.size()==0) return 1; return trackVerticalOffset.lastKey() + trackVerticalOffset.lastEntry().getValue().getHeight(); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java index 4add590..e2e3712 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java @@ -31,6 +31,7 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.ScrollBar; import com.google.common.collect.Lists; import com.minres.scviewer.database.EventEntry; @@ -45,21 +46,22 @@ import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.ZoomKind; import com.minres.scviewer.database.ui.swt.Constants; +import com.minres.scviewer.database.ui.swt.internal.slider.TimeZoomScrollbar; public class WaveformCanvas extends Canvas implements IWaveformZoom{ public static final long ZOOM_FIT = -2; public static final long ZOOM_FULL = -1; - + private boolean doubleBuffering = true; IWaveformStyleProvider styleProvider; private int scaleMagnitude = 6; - + private long scaleFactor = Constants.POWERS_OF_TEN[scaleMagnitude]; - + private long maxTime; protected Point origin; /* original size */ @@ -80,8 +82,9 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ private List cursorPainters; - IScrollBar horizontal; - IScrollBar vertical; + private TimeZoomScrollbar horizontal; + + private ScrollBar vertical; HashMap wave2painterMap; /** @@ -92,13 +95,13 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ * @param style * the style of this control. */ - public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider, IWaveformScrollBarProvider scrollbarProvider) { - super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND); + public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider, TimeZoomScrollbar.IProvider scrollbarProvider) { + super(parent, (style & ~SWT.H_SCROLL) | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL ); this.styleProvider=styleProvider; addControlListener(new ControlAdapter() { /* resize listener. */ @Override public void controlResized(ControlEvent event) { - syncScrollBars(); + syncSb(); } }); addPaintListener((final PaintEvent event) -> paint(event.gc)); @@ -108,8 +111,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ cursorPainters= new ArrayList<>(); wave2painterMap=new HashMap<>(); - horizontal = (style& SWT.H_SCROLL)==0?scrollbarProvider.getHorizontalSb() : new ScrollBarAdapter(getHorizontalBar()); - vertical = (style& SWT.V_SCROLL)==0?scrollbarProvider.getVerticalSb() : new ScrollBarAdapter(getVerticalBar()); + horizontal = scrollbarProvider.getScrollBar(); + vertical = getVerticalBar(); initScrollBars(); // order is important: it is bottom to top trackAreaPainter=new TrackAreaPainter(this); @@ -118,10 +121,10 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ painterList.add(arrowPainter); rulerPainter=new RulerPainter(this); painterList.add(rulerPainter); - CursorPainter cp = new CursorPainter(this, scaleFactor * 10, cursorPainters.size()-1); + CursorPainter cp = new CursorPainter(this, getScale() * 10, cursorPainters.size()-1); painterList.add(cp); cursorPainters.add(cp); - CursorPainter marker = new CursorPainter(this, scaleFactor * 100, cursorPainters.size()-1); + CursorPainter marker = new CursorPainter(this, getScale() * 100, cursorPainters.size()-1); painterList.add(marker); cursorPainters.add(marker); wave2painterMap=new HashMap<>(); @@ -154,12 +157,12 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void setOrigin(int x, int y) { checkWidget(); if(x<=0) horizontal.setSelection(-x); - x = -horizontal.getSelection(); + x = -horizontal.getSelection()[0]; if(y<=0) vertical.setSelection(-y); y = -vertical.getSelection(); origin.x = x; origin.y = y; - syncScrollBars(); + syncSb(); } @Override @@ -169,14 +172,14 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void setMaxTime(long maxTime) { this.maxTime = maxTime; - syncScrollBars(); + syncSb(); } @Override public long getScale() { return scaleFactor; } - + @Override public void setScale(long factor) { setScalingFactor(factor, (getMaxVisibleTime()+getMinVisibleTime())/2); @@ -208,37 +211,41 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ factor=1; else if(factor>maxFactor) factor=maxFactor; - if(factor!=scaleFactor || (getMaxVisibleTime()+getMinVisibleTime()/2) != centerTime) { - scaleFactor = factor; - scaleMagnitude = 0; - for(int i=Constants.POWERS_OF_TEN.length-1; i>0; i--) { - if(scaleFactor>=Constants.POWERS_OF_TEN[i]) { - scaleMagnitude = i; - break; - } - } + if(factor!=getScale() || (getMaxVisibleTime()+getMinVisibleTime()/2) != centerTime) { + updateScaleFactor(factor); ITx tx = arrowPainter.getTx(); arrowPainter.setTx(null); /* * xc = tc/oldScaleFactor * xoffs = xc+origin.x * xcn = tc/newScaleFactor - * t0n = (xcn-xoffs)*scaleFactor + * t0n = (xcn-xoffs)*getScale() */ long xoffs = clientAreaWidth/2; - long xcn=centerTime/scaleFactor; // new total x-offset + long xcn=centerTime/getScale(); // new total x-offset long originX=xcn-xoffs; if(originX>0) { origin.x=(int) -originX; // new cursor time offset relative to left border }else { origin.x=0; } - syncScrollBars(); + syncSb(); arrowPainter.setTx(tx); redraw(); } } + private void updateScaleFactor(long factor) { + scaleFactor = factor; + scaleMagnitude = 0; + for(int i=Constants.POWERS_OF_TEN.length-1; i>0; i--) { + if(scaleFactor>=Constants.POWERS_OF_TEN[i]) { + scaleMagnitude = i; + break; + } + } + } + @Override public String timeToString(long time) { int idx = scaleMagnitude/3; @@ -247,7 +254,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ } public long getTimeForOffset(int xOffset){ - return (xOffset-origin.x) * scaleFactor; + return (xOffset-origin.x) * getScale(); } public void addPainter(IPainter painter) { @@ -267,7 +274,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ void clearAllWaveformPainter(boolean update) { trackAreaPainter.trackVerticalOffset.clear(); wave2painterMap.clear(); - if(update) syncScrollBars(); + if(update) syncSb(); } public void addWaveformPainter(IWaveformPainter painter) { @@ -277,7 +284,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ void addWaveformPainter(IWaveformPainter painter, boolean update) { trackAreaPainter.addTrackPainter(painter); wave2painterMap.put(painter.getTrackEntry().waveform, painter); - if(update) syncScrollBars(); + if(update) syncSb(); } public List getCursorPainters() { @@ -291,9 +298,18 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ horizontal.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (painterList.isEmpty()) - return; - setOrigin(-horizontal.getSelection(), origin.y); + if (!painterList.isEmpty()) { + int[] sel = horizontal.getSelection(); + //long width = maxTime / getScale(); + int currentThumbWidth = getClientArea().width; + int newThumbWidth = sel[1]-sel[0]; + if(currentThumbWidth!=newThumbWidth) { + long newScaleFactor =getScale()*newThumbWidth/currentThumbWidth; + updateScaleFactor(Math.max(1, newScaleFactor)); + } + origin.x=-sel[0]; + syncSb(); + } } }); vertical.setEnabled(false); @@ -301,9 +317,10 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ vertical.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (painterList.isEmpty()) - return; - setOrigin(origin.x, -vertical.getSelection()); + if (!painterList.isEmpty()) { + origin.y=-vertical.getSelection(); + syncSb(); + } } }); } @@ -313,48 +330,50 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ * range, it will correct it. This function considers only following factors * : transform, image size, client area. */ - public void syncScrollBars() { - if (painterList.isEmpty()) { - redraw(); - return; + public void syncSb() { + if (!painterList.isEmpty()) { + syncHSb(); + syncVSb(); + fireSelectionEvent(); } - int height = trackAreaPainter.getHeight(); // incl. Ruler - long width = maxTime / scaleFactor; - Rectangle clientArea=getClientArea(); - int clientWidthw = clientArea.width; - horizontal.setIncrement(clientWidthw / 100); - horizontal.setPageIncrement(clientWidthw/2); - if (width > clientWidthw) { /* image is wider than client area */ - horizontal.setMinimum(0); - horizontal.setMaximum((int)width); - horizontal.setEnabled(true); - if (-origin.x > horizontal.getMaximum() - clientWidthw) { - origin.x = -horizontal.getMaximum() + clientWidthw; - } - } else { /* image is narrower than client area */ - horizontal.setEnabled(false); - } - horizontal.setThumb(clientWidthw); - horizontal.setSelection(-origin.x); + this.getDisplay().asyncExec(() -> {redraw();}); + } - int clientHeighth = clientArea.height; - vertical.setIncrement(clientHeighth / 100); - vertical.setPageIncrement(clientHeighth/2); - if (height > clientHeighth) { /* image is higher than client area */ + private void syncVSb() { + Rectangle clientArea=getClientArea(); + int height = trackAreaPainter.getHeight(); // incl. Ruler + int clientHeight = clientArea.height; + vertical.setIncrement(clientHeight / 100); + vertical.setPageIncrement(clientHeight/2); + if (height > clientHeight) { /* image is higher than client area */ vertical.setMinimum(0); vertical.setMaximum(height); vertical.setEnabled(true); - if ( -origin.y > vertical.getMaximum() - clientHeighth) { - origin.y = -vertical.getMaximum() + clientHeighth; + if ( -origin.y > vertical.getMaximum() - clientHeight) { + origin.y = -vertical.getMaximum() + clientHeight; } } else { /* image is less higher than client area */ - vertical.setMaximum(clientHeighth); + vertical.setMaximum(clientHeight); vertical.setEnabled(false); } - vertical.setThumb(clientHeighth); + vertical.setThumb(clientHeight); vertical.setSelection(-origin.y); - redraw(); - fireSelectionEvent(); + } + + private void syncHSb() { + horizontal.setEnabled(wave2painterMap.size()>0); + Rectangle clientArea=getClientArea(); + long width = maxTime / getScale(); + int clientWidth = clientArea.width; + horizontal.setIncrement(clientWidth / 100); + horizontal.setPageIncrement(clientWidth/2); + horizontal.setMinimum(0); + horizontal.setMaximum((int)width); + if (width>0 && -origin.x > horizontal.getMaximum() - clientWidth) { + origin.x = -horizontal.getMaximum() + clientWidth; + } + horizontal.setSelection(new int[] {Math.max(-origin.x,0), Math.min(clientWidth-origin.x, horizontal.getMaximum())}); + horizontal.setButtonsEnabled(width > clientWidth); } /* Paint function */ @@ -404,7 +423,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ result.add(entry.getValue().getTrackEntry()); } } else if (p instanceof CursorPainter) { - if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/scaleFactor) < 2) { + if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/getScale()) < 2) { result.add(p); } } @@ -432,8 +451,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ } public void reveal(ITx tx) { - int lower = (int) (tx.getBeginTime() / scaleFactor); - int higher = (int) (tx.getEndTime() / scaleFactor); + int lower = (int) (tx.getBeginTime() / getScale()); + int higher = (int) (tx.getEndTime() / getScale()); Point size = getSize(); size.x -= vertical.getSize().x + 2; size.y -= horizontal.getSize().y; @@ -479,7 +498,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ } public void reveal(long time) { - int scaledTime = (int) (time / scaleFactor); + int scaledTime = (int) (time / getScale()); Point size = getSize(); size.x -= vertical.getSize().x + 2; size.y -= horizontal.getSize().y; @@ -492,7 +511,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ @Override public void centerAt(long time) { - int scaledTime = (int) (time / scaleFactor); + int scaledTime = (int) (time / getScale()); int newX = -scaledTime+getWidth()/2; setOrigin(newX>0?0:newX, origin.y); } @@ -529,15 +548,15 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ } } - + @Override public long getMaxVisibleTime() { - return (getClientArea().width-origin.x)*scaleFactor; + return (getClientArea().width-origin.x)*getScale(); } @Override public long getMinVisibleTime() { - return -origin.x * scaleFactor; + return -origin.x * getScale(); } @Override @@ -545,7 +564,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ long duration = getMaxVisibleTime()-getMinVisibleTime(); if(time>0) { if((time+duration) { - GC gc = paintEvent.gc; - gc.setBackground(buttonColor); - gc.setForeground(buttonColor); - int left = paintEvent.x+4; - int top = paintEvent.y+5; - int width=paintEvent.width-11; - int height= paintEvent.height-10; - int[] triangle = new int[] { - left, top+height/2, - left+width, top, - left+width, top+height}; - gc.fillPolygon( triangle ); - gc.drawPolygon( triangle ); - }); - scrlLeft.addSelectionListener(new SelectionAdapter() { - public void widgetSelected (SelectionEvent e){ - slider.setSelection(slider.getSelection()-10); - } - }); - scrlLeft.redraw(); - - slider = new Slider(this, SWT.NONE); - slider.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); - GridData gd_canvas = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); - gd_canvas.heightHint = 16; - slider.setLayoutData(gd_canvas); - - Button scrlRight = new Button(this, /*SWT.BORDER |*/ SWT.FLAT | SWT.CENTER); - scrlRight.setAlignment(SWT.CENTER); - GridData gd_scrlRight = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); - gd_scrlRight.heightHint = 16; - gd_scrlRight.widthHint = 16; - scrlRight.setLayoutData(gd_scrlRight); - scrlRight.addPaintListener(paintEvent -> { - GC gc = paintEvent.gc; - gc.setBackground(buttonColor); - gc.setForeground(buttonColor); - int left = paintEvent.x+6; - int top = paintEvent.y+5; - int width=paintEvent.width-11; - int height= paintEvent.height-10; - int[] triangle = new int[] { - left, top, - left+width, top+height/2, - left, top+height}; - gc.fillPolygon( triangle ); - gc.drawPolygon( triangle ); - }); - scrlRight.addSelectionListener(new SelectionAdapter() { - public void widgetSelected (SelectionEvent e){ - slider.setSelection(slider.getSelection()+10); - } - }); - redraw(); - } -} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 0eb64c3..80f92a4 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -54,9 +54,7 @@ import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.TextLayout; @@ -93,10 +91,7 @@ import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; -import com.minres.scviewer.database.ui.swt.internal.slider.ImageButton; -import com.minres.scviewer.database.ui.swt.internal.slider.RangeSlider; -import com.minres.scviewer.database.ui.swt.internal.slider.ZoomingScrollbar; -import com.minres.scviewer.database.ui.swt.sb.FlatScrollBar; +import com.minres.scviewer.database.ui.swt.internal.slider.TimeZoomScrollbar; public class WaveformView implements IWaveformView { @@ -344,21 +339,16 @@ public class WaveformView implements IWaveformView { gl_waveformPane.marginHeight = 0; waveformPane.setLayout(gl_waveformPane); - IWaveformScrollBarProvider sbProvider = new IWaveformScrollBarProvider() { - @Override - public IScrollBar getVerticalSb() { - return null; - } + waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider, new TimeZoomScrollbar.IProvider() { @Override - public IScrollBar getHorizontalSb() { - ZoomingScrollbar timeSliderPane = new ZoomingScrollbar(waveformPane, SWT.NONE); + public TimeZoomScrollbar getScrollBar() { + TimeZoomScrollbar timeSliderPane = new TimeZoomScrollbar(waveformPane, SWT.NONE); GridData gd_timeSliderPane = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); timeSliderPane.setLayoutData(gd_timeSliderPane); return timeSliderPane; } - }; - waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider, sbProvider); + }); waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); // create the name pane @@ -551,7 +541,7 @@ public class WaveformView implements IWaveformView { tracksVerticalHeight += streamEntry.height; even = !even; } - waveformCanvas.syncScrollBars(); + waveformCanvas.syncSb(); nameList.setSize(nameMaxWidth + 15, tracksVerticalHeight); nameListScrolled.setMinSize(nameMaxWidth + 15, tracksVerticalHeight); nameList.redraw(); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java index 3c3ca72..cc4a667 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java @@ -15,6 +15,7 @@ public class ImageButton extends Composite private Image hoverImage; private Image normalImage; private Image pressedImage; + private Image disabledImage; private int width; private int height; private boolean hover; @@ -24,8 +25,7 @@ public class ImageButton extends Composite private ActionTimer.TimerAction timerAction; public ImageButton(Composite parent, int style) { - super(parent, style); - + super(parent, style); timerAction = new ActionTimer.TimerAction() { @Override public void run() { @@ -37,30 +37,28 @@ public class ImageButton extends Composite } }; actionTimer = new ActionTimer(timerAction, this.getDisplay() ); - addListener(SWT.Dispose, event -> { if (hoverImage != null) hoverImage.dispose(); if (normalImage != null) normalImage.dispose(); if (pressedImage != null) pressedImage.dispose(); + if (disabledImage != null) disabledImage.dispose(); }); - addListener(SWT.Paint, event -> { paintControl(event); }); - addListener(SWT.MouseDown, event -> { + if(!isEnabled()) return; pressed=true; notifyListeners(); if(autoFire) actionTimer.activate(); redraw(); }); - addListener(SWT.MouseUp, event -> { pressed=false; redraw(); }); - addListener(SWT.MouseMove, event -> { + if(!isEnabled()) return; Point sz = ((ImageButton)event.widget).getSize(); final boolean within_x = event.x>0 && event.x0 && event.y1? - new Image(d, imgs[1], SWT.IMAGE_COPY): - new Image(d,imgs[0],SWT.IMAGE_GRAY); - pressedImage = imgs.length>2? - new Image(d, imgs[2], SWT.IMAGE_COPY): - new Image(d,imgs[0],SWT.IMAGE_DISABLE); + normalImage = new Image(d, imgs[0], SWT.IMAGE_COPY); + hoverImage = new Image(d, imgs[1], SWT.IMAGE_COPY); + pressedImage = new Image(d, imgs[2], SWT.IMAGE_COPY); + disabledImage = new Image(d, imgs[0], SWT.IMAGE_DISABLE); width = imgs[0].getBounds().width; height = imgs[0].getBounds().height; redraw(); } @Override - public Point computeSize(int wHint, int hHint, boolean changed) - { + public Point computeSize(int wHint, int hHint, boolean changed) { int overallWidth = width; int overallHeight = height; - - /* Consider hints */ if (wHint != SWT.DEFAULT && wHint < overallWidth) overallWidth = wHint; - if (hHint != SWT.DEFAULT && hHint < overallHeight) overallHeight = hHint; - - /* Return computed dimensions plus border */ return new Point(overallWidth + 2, overallHeight + 2); } /** @@ -185,6 +174,4 @@ public class ImageButton extends Composite public void setAutoFire(boolean autoFire) { this.autoFire = autoFire; } - - } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java index 0b78cd4..3f4bd1b 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java @@ -55,6 +55,7 @@ public class RangeSlider extends Canvas { private static int minWidth = 18; private static int minHeight = 18; private static int imgWidth = 8; + private static int minThumbWidth = 5; private int minimum; private int maximum; private int lowerValue; @@ -143,17 +144,6 @@ public class RangeSlider extends Canvas { isOn = (style & SWT.ON) == SWT.ON; selectedElement = isFullSelection ? BOTH : LOWER; -// addListener(SWT.Dispose, event -> { -// SWTResourceManager.dsafeDispose(slider); -// SWTGraphicUtil.safeDispose(sliderHover); -// SWTGraphicUtil.safeDispose(sliderDrag); -// SWTGraphicUtil.safeDispose(sliderSelected); -// -// SWTGraphicUtil.safeDispose(vSlider); -// SWTGraphicUtil.safeDispose(vSliderHover); -// SWTGraphicUtil.safeDispose(vSliderDrag); -// SWTGraphicUtil.safeDispose(vSliderSelected); -// }); addMouseListeners(); addListener(SWT.Resize, event -> { }); @@ -300,14 +290,14 @@ public class RangeSlider extends Canvas { } else if ((selectedElement & UPPER) != 0) { upperValue = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; if (!isSmooth) { - upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; + upperValue = Math.min(lowerValue, (int) (Math.ceil(upperValue / increment) * increment) - increment); } checkUpperValue(); handleToolTip(upperValue); } else { lowerValue = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; if (!isSmooth) { - lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; + lowerValue = Math.max(upperValue, (int) (Math.ceil(lowerValue / increment) * increment) - increment); } checkLowerValue(); handleToolTip(lowerValue); @@ -380,11 +370,12 @@ public class RangeSlider extends Canvas { return; } final Image img = orientation == SWT.HORIZONTAL ? slider[0] : vSlider; + final Rectangle imgBounds = img.getBounds(); final int x = e.x, y = e.y; - lowerHover = x >= coordLower.x && x <= coordLower.x + img.getBounds().width && y >= coordLower.y && y <= coordLower.y + img.getBounds().height; + lowerHover = x >= coordLower.x && x <= coordLower.x + imgBounds.width && y >= coordLower.y && y <= coordLower.y + imgBounds.height; upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && // - x >= coordUpper.x && x <= coordUpper.x + img.getBounds().width && // - y >= coordUpper.y && y <= coordUpper.y + img.getBounds().height; + x >= coordUpper.x && x <= coordUpper.x + imgBounds.width && // + y >= coordUpper.y && y <= coordUpper.y + imgBounds.height; lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover; if (!lowerHover && !upperHover && isFullSelection && isBetweenKnobs(x, y)) { lowerHover = upperHover = true; @@ -403,7 +394,7 @@ public class RangeSlider extends Canvas { int value = -1; final Rectangle clientArea = getClientArea(); if (orientation == SWT.HORIZONTAL) { - if (x < 9 + clientArea.width - 20 && x >= 9 && y >= 9 && y <= 9 + clientArea.height - 20) { + if (x < clientArea.width - 2*imgWidth && x >= imgWidth && y >= minHeight/3 && y <= clientArea.height - minHeight/3) { value = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; } } else if (y < 9 + clientArea.height - 20 && y >= 9 && x >= 9 && x <= 9 + clientArea.width - 20) { @@ -579,11 +570,11 @@ public class RangeSlider extends Canvas { if (lowerValue < minimum) { lowerValue = minimum; } - if (lowerValue > maximum) { - lowerValue = maximum; + if (lowerValue > (maximum-minThumbWidth)) { + lowerValue = (maximum-minThumbWidth); } - if (lowerValue > upperValue) { - lowerValue = upperValue; + if (lowerValue > (upperValue-minThumbWidth)) { + lowerValue = (upperValue-minThumbWidth); } } @@ -591,14 +582,14 @@ public class RangeSlider extends Canvas { * Check if the upper value is in ranges */ private void checkUpperValue() { - if (upperValue < minimum) { - upperValue = minimum; + if (upperValue < (minimum+minThumbWidth)) { + upperValue = minimum+minThumbWidth; } if (upperValue > maximum) { upperValue = maximum; } - if (upperValue < lowerValue) { - upperValue = lowerValue; + if (upperValue < (lowerValue+minThumbWidth)) { + upperValue = lowerValue+minThumbWidth; } } @@ -1422,10 +1413,19 @@ public class RangeSlider extends Canvas { * @see #getMaximum() */ public void setSelection(final int lowerValue, final int upperValue) { + setSelection(lowerValue, upperValue, false); + } + public void setSelection(final int lowerValue, final int upperValue, boolean update) { checkWidget(); if (lowerValue <= upperValue && lowerValue >= minimum && upperValue <= maximum && (this.lowerValue != lowerValue || this.upperValue != upperValue)) { this.lowerValue = lowerValue; this.upperValue = upperValue; + if(update) { + Event e = new Event(); + e.type=SWT.Selection; + e.doit=true; + validateNewValues(e); + } redraw(); } } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java similarity index 50% rename from plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java rename to plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java index 077da38..ecca946 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomingScrollbar.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java @@ -1,5 +1,7 @@ package com.minres.scviewer.database.ui.swt.internal.slider; +import java.text.Format; + import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -10,16 +12,21 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.wb.swt.SWTResourceManager; -import com.minres.scviewer.database.ui.swt.internal.IScrollBar; +public class TimeZoomScrollbar extends Composite { + + static public interface IProvider { + TimeZoomScrollbar getScrollBar(); + } -public class ZoomingScrollbar extends Composite implements IScrollBar { - RangeSlider timeSlider; + final RangeSlider timeSlider; + final ImageButton leftButton; + final ImageButton rightButton; /** * Create the composite. * @param parent * @param style */ - public ZoomingScrollbar(Composite parent, int style) { + public TimeZoomScrollbar(Composite parent, int style) { super(parent, SWT.NO_FOCUS); GridLayout gridLayout = new GridLayout(3, false); gridLayout.horizontalSpacing = 0; @@ -27,84 +34,100 @@ public class ZoomingScrollbar extends Composite implements IScrollBar { gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; setLayout(gridLayout); - //setBackground(SWTResourceManager.getColor(SWT.COLOR_RED)); - ImageButton b1 = new ImageButton(this, SWT.NONE); - GridData gd_b1 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); - gd_b1.widthHint=14; - gd_b1.heightHint=18; - b1.setLayoutData(gd_b1); - b1.setImage(new Image[] { - SWTResourceManager.getImage(this.getClass(), "arrow_left_hover.png"), + leftButton = new ImageButton(this, SWT.NONE); + GridData gd_leftButton = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_leftButton.widthHint=14; + gd_leftButton.heightHint=18; + leftButton.setLayoutData(gd_leftButton); + leftButton.setImage(new Image[] { SWTResourceManager.getImage(this.getClass(), "arrow_left.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_left_hover.png"), SWTResourceManager.getImage(this.getClass(), "arrow_left_pressed.png")}); - b1.addSelectionListener(new SelectionAdapter() { + leftButton.setAutoFire(true); + + timeSlider = new RangeSlider(this, SWT.ON|SWT.HIGH|SWT.SMOOTH|SWT.CONTROL); + timeSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + + rightButton = new ImageButton(this, SWT.NONE); + GridData gd_rightButton = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_rightButton.widthHint=18; + gd_rightButton.heightHint=18; + rightButton.setLayoutData(gd_rightButton); + rightButton.setImage(new Image[] { + SWTResourceManager.getImage(this.getClass(), "arrow_right.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_right_hover.png"), + SWTResourceManager.getImage(this.getClass(), "arrow_right_pressed.png")}); + rightButton.setAutoFire(true); + + leftButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int[] value = timeSlider.getSelection(); int diff = value[1]-value[0]; int newLow = Math.max(0, value[0]-Math.max(1, diff/10)); - timeSlider.setSelection(newLow, newLow+diff); + timeSlider.setSelection(newLow, newLow+diff, true); } }); - timeSlider = new RangeSlider(this, /*SWT.ON|*/SWT.HIGH|SWT.SMOOTH|SWT.CONTROL); - GridData gd_timeSlide = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); - timeSlider.setLayoutData(gd_timeSlide); - - ImageButton b2 = new ImageButton(this, SWT.NONE); - GridData gd_b2 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); - gd_b2.widthHint=18; - gd_b2.heightHint=18; - b2.setLayoutData(gd_b2); - b2.setImage(new Image[] { - SWTResourceManager.getImage(this.getClass(), "arrow_right_hover.png"), - SWTResourceManager.getImage(this.getClass(), "arrow_right.png"), - SWTResourceManager.getImage(this.getClass(), "arrow_right_pressed.png")}); - b2.addSelectionListener(new SelectionAdapter() { + rightButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int[] value = timeSlider.getSelection(); int diff = value[1]-value[0]; int newHigh = Math.min(timeSlider.getMaximum(), value[1] + diff/10); - timeSlider.setSelection(newHigh-diff, newHigh); + timeSlider.setSelection(newHigh-diff, newHigh, true); } }); } @Override - public void setSelection(int i) { - timeSlider.setLowerValue(i); + public void setEnabled (boolean enabled) { + timeSlider.setEnabled(enabled); + leftButton.setEnabled(enabled); + rightButton.setEnabled(enabled); + super.setEnabled(enabled); + redraw(); } - @Override - public int getSelection() { - return timeSlider.getLowerValue(); + public void setButtonsEnabled (boolean enabled) { + leftButton.setEnabled(enabled); + rightButton.setEnabled(enabled); + redraw(); + } + public void setToolTipFormatter(Format formatter){ + timeSlider.setToolTipFormatter(formatter); + } + public void setToolTipText(String string) { + timeSlider.setToolTipText(string); + } + public void setSelection(int sel) { + timeSlider.setLowerValue(sel); + } + public void setSelection(int[] sel) { + assert(sel.length==2); + timeSlider.setSelection(sel[0], sel[1]); + } + public int[] getSelection() { + return timeSlider.getSelection(); } - @Override public void addSelectionListener(SelectionListener selectionListener) { timeSlider.addSelectionListener(selectionListener); } - @Override public void setIncrement(int value) { timeSlider.setIncrement(value); } - @Override public void setPageIncrement(int value) { timeSlider.setPageIncrement(value); } - @Override public void setMinimum(int value) { timeSlider.setMinimum(value); } - @Override public void setMaximum(int value) { timeSlider.setMaximum(value); } - @Override public int getMaximum() { return timeSlider.getMaximum(); } - @Override - public void setThumb(int w) { - timeSlider.setUpperValue(timeSlider.getLowerValue()+w); + public int getMinimum() { + return timeSlider.getMinimum(); } } From bd0629301b8df62c731f9f2e8ef319ceb5806e92 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 6 Jan 2022 17:48:40 +0100 Subject: [PATCH 5/8] add next increment - basically working --- .../ui/swt/internal/WaveformCanvas.java | 50 +- .../ui/swt/internal/WaveformView.java | 19 +- .../ui/swt/internal/slider/ImageButton.java | 49 +- .../ui/swt/internal/slider/RangeSlider.java | 1305 +++-------------- .../internal/slider/TimeZoomScrollbar.java | 20 +- .../ui/swt/internal/slider/h-slider-drag.png | Bin 1057 -> 0 bytes .../ui/swt/internal/slider/h-slider-hover.png | Bin 1057 -> 0 bytes .../swt/internal/slider/h-slider-normal.png | Bin 1055 -> 0 bytes .../swt/internal/slider/h-slider-selected.png | Bin 1041 -> 0 bytes .../ui/swt/internal/slider/marker_l.png | Bin 374 -> 350 bytes .../ui/swt/internal/slider/marker_l_bl.png | Bin 353 -> 0 bytes .../ui/swt/internal/slider/marker_l_bl_lt.png | Bin 343 -> 0 bytes .../ui/swt/internal/slider/marker_l_hover.png | Bin 0 -> 336 bytes .../ui/swt/internal/slider/marker_l_lt.png | Bin 385 -> 0 bytes .../swt/internal/slider/marker_l_pressed.png | Bin 0 -> 352 bytes .../ui/swt/internal/slider/marker_r.png | Bin 358 -> 329 bytes .../ui/swt/internal/slider/marker_r_bl.png | Bin 386 -> 0 bytes .../ui/swt/internal/slider/marker_r_bl_lt.png | Bin 366 -> 0 bytes .../ui/swt/internal/slider/marker_r_hover.png | Bin 0 -> 326 bytes .../ui/swt/internal/slider/marker_r_lt.png | Bin 345 -> 0 bytes .../swt/internal/slider/marker_r_pressed.png | Bin 0 -> 349 bytes .../ui/swt/internal/slider/slider-drag.png | Bin 1085 -> 0 bytes .../ui/swt/internal/slider/slider-hover.png | Bin 1083 -> 0 bytes .../ui/swt/internal/slider/slider-normal.png | Bin 1072 -> 0 bytes .../swt/internal/slider/slider-selected.png | Bin 430 -> 0 bytes .../e4/application/parts/WaveformViewer.java | 11 +- 26 files changed, 330 insertions(+), 1124 deletions(-) delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-drag.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-hover.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-normal.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-selected.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_bl.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_bl_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_hover.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_l_pressed.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_hover.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_lt.png create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_pressed.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-drag.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-hover.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-normal.png delete mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-selected.png diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java index e2e3712..5f7cde9 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java @@ -84,6 +84,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ private TimeZoomScrollbar horizontal; + private int[] lastHorSelection; + private ScrollBar vertical; HashMap wave2painterMap; @@ -156,10 +158,10 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void setOrigin(int x, int y) { checkWidget(); - if(x<=0) horizontal.setSelection(-x); - x = -horizontal.getSelection()[0]; - if(y<=0) vertical.setSelection(-y); - y = -vertical.getSelection(); +// if(x<=0) horizontal.setSelection(-x); +// x = -horizontal.getSelection()[0]; +// if(y<=0) vertical.setSelection(-y); +// y = -vertical.getSelection(); origin.x = x; origin.y = y; syncSb(); @@ -300,18 +302,24 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void widgetSelected(SelectionEvent event) { if (!painterList.isEmpty()) { int[] sel = horizontal.getSelection(); - //long width = maxTime / getScale(); - int currentThumbWidth = getClientArea().width; - int newThumbWidth = sel[1]-sel[0]; - if(currentThumbWidth!=newThumbWidth) { - long newScaleFactor =getScale()*newThumbWidth/currentThumbWidth; - updateScaleFactor(Math.max(1, newScaleFactor)); + long lowerTime = sel[0]*maxTime/horizontal.getMaximum(); + long upperTime = sel[1]*maxTime/horizontal.getMaximum(); + if(sel[1]-sel[0] != lastHorSelection[1]-lastHorSelection[0]) { + long time_diff = upperTime-lowerTime; + long factor = time_diff/getClientArea().width; + setScalingFactor(factor, lowerTime+time_diff/2); + } else { + origin.x = -(int) (lowerTime / getScale()); + event.widget.getDisplay().asyncExec(() -> {redraw();}); } - origin.x=-sel[0]; - syncSb(); + lastHorSelection=sel; } } }); + horizontal.setMinimum(0); + horizontal.setMaximum(10000); + lastHorSelection = horizontal.getSelection(); + vertical.setEnabled(false); vertical.setVisible(true); vertical.addSelectionListener(new SelectionAdapter() { @@ -319,7 +327,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void widgetSelected(SelectionEvent event) { if (!painterList.isEmpty()) { origin.y=-vertical.getSelection(); - syncSb(); + fireSelectionEvent(); + event.widget.getDisplay().asyncExec(() -> {redraw();}); } } }); @@ -363,16 +372,15 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ private void syncHSb() { horizontal.setEnabled(wave2painterMap.size()>0); Rectangle clientArea=getClientArea(); - long width = maxTime / getScale(); int clientWidth = clientArea.width; - horizontal.setIncrement(clientWidth / 100); - horizontal.setPageIncrement(clientWidth/2); - horizontal.setMinimum(0); - horizontal.setMaximum((int)width); - if (width>0 && -origin.x > horizontal.getMaximum() - clientWidth) { - origin.x = -horizontal.getMaximum() + clientWidth; + if(maxTime>0) { + int lower = (int) ( -origin.x * getScale() * horizontal.getMaximum() / maxTime); + int upper = (int) ((clientWidth-origin.x) * getScale() * horizontal.getMaximum() / maxTime); + int[] curSel = horizontal.getSelection(); + lastHorSelection = new int[] {Math.max(lower,0), Math.min(upper, horizontal.getMaximum())}; + horizontal.setSelection(lastHorSelection); } - horizontal.setSelection(new int[] {Math.max(-origin.x,0), Math.min(clientWidth-origin.x, horizontal.getMaximum())}); + long width = maxTime / getScale(); horizontal.setButtonsEnabled(width > clientWidth); } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 80f92a4..755af81 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -267,11 +267,24 @@ public class WaveformView implements IWaveformView { switch (e.type) { case SWT.MouseWheel: if((e.stateMask & SWT.CTRL) != 0) { - if(e.count<0) + if(e.count<0) // up scroll waveformCanvas.setScale(waveformCanvas.getScale()*11/10); - else + else // down scroll waveformCanvas.setScale(waveformCanvas.getScale()*10/11); - } + e.doit=false; + } else if((e.stateMask & SWT.SHIFT) != 0) { + long upper = waveformCanvas.getMaxVisibleTime(); + long lower = waveformCanvas.getMinVisibleTime(); + long duration = upper-lower; + if(e.count<0) { // up scroll + long newLower = Math.min(waveformCanvas.getMaxTime()-duration, lower+duration/10); + waveformCanvas.setMinVisibleTime(newLower); + } else {// down scroll + long newLower = Math.max(0, lower-duration/10); + waveformCanvas.setMinVisibleTime(newLower); + } + e.doit=false; + } break; case SWT.MouseDown: start = new Point(e.x, e.y); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java index cc4a667..91841fb 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ImageButton.java @@ -2,6 +2,9 @@ package com.minres.scviewer.database.ui.swt.internal.slider; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; @@ -46,24 +49,36 @@ public class ImageButton extends Composite addListener(SWT.Paint, event -> { paintControl(event); }); - addListener(SWT.MouseDown, event -> { - if(!isEnabled()) return; - pressed=true; - notifyListeners(); - if(autoFire) actionTimer.activate(); - redraw(); + addMouseTrackListener(new MouseTrackAdapter() { + public void mouseEnter(MouseEvent arg0) { + if(isEnabled()) { + hover=true; + redraw(); + } + } + public void mouseExit(MouseEvent arg0) { + if(isEnabled()) { + hover=false; + redraw(); + } + } }); - addListener(SWT.MouseUp, event -> { - pressed=false; - redraw(); - }); - addListener(SWT.MouseMove, event -> { - if(!isEnabled()) return; - Point sz = ((ImageButton)event.widget).getSize(); - final boolean within_x = event.x>0 && event.x0 && event.y - *
- *
Styles:
- *
BORDER
- *
HORIZONTAL
- *
VERTICAL
- *
CONTROL - Allow key and mouse manipulation to control both lower and - * upper value thumbs simultaneously
- *
ON - Indicates that selection listeners are notified continuously during - * thumb drag events. Otherwise, notification occurs only after the drag event - * terminates.
- *
HIGH - Indicates high quality tick marks are generated dynamically to a - * factor of the pageIncrement or increment. Otherwise, tick marks divide the - * scale evenly into ten parts.
- *
SMOOTH - Indicates mouse manipulation of upper and lower values are - * computed smoothly from the exact mouse cursor position disregarding the - * increment value. Otherwise, values are constrained to an incremental - * value.
- *
Events:
- *
Selection
- *
- *

- *

- * Note: Styles HORIZONTAL and VERTICAL are mutually exclusive. - *

- */ public class RangeSlider extends Canvas { - private static final byte NONE = 0; - private static final byte UPPER = 1 << 0; - private static final byte LOWER = 1 << 1; - private static final byte BOTH = UPPER | LOWER; + private static final int NONE = 0; + private static final int UPPER = 1 << 0; + private static final int LOWER = 1 << 1; + private static final int BOTH = UPPER | LOWER; - private static int minWidth = 18; - private static int minHeight = 18; - private static int imgWidth = 8; - private static int minThumbWidth = 5; + private final int minHeight; + private final int markerWidth; + private final int thumbWidth = 0; + private final Image[] slider, sliderHover, sliderDrag; + private int minimum; private int maximum; private int lowerValue; private int upperValue; - private final Image[] slider, sliderHover, sliderDrag, sliderSelected; - private final Image vSlider, vSliderHover, vSliderDrag, vSliderSelected; - private int orientation; + private int increment; private int pageIncrement; - private byte selectedElement, priorSelectedElement; - private boolean dragInProgress; + private int selectedElement; private boolean upperHover, lowerHover; private int previousUpperValue, previousLowerValue; private int startDragUpperValue, startDragLowerValue; private Point startDragPoint; - private boolean hasFocus; private final boolean isSmooth; - private final boolean isFullSelection; + private final boolean isFullSelection=false; private final boolean isHighQuality; private final boolean isOn; private Format toolTipFormatter; private String clientToolTipText; + private StringBuffer toolTip; + private Point coordUpper; + private Point coordLower; - /** - * Constructs a new instance of this class given its parent and a style value - * describing its behavior and appearance. - *

- * The style value is either one of the style constants defined in class - * SWT which is applicable to instances of this class, or must be - * built by bitwise OR'ing together (that is, using the - * int "|" operator) two or more of those SWT style - * constants. The class description lists the style constants that are - * applicable to the class. Style bits are also inherited from superclasses. - *

- * - * @param parent a composite control which will be the parent of the new - * instance (cannot be null) - * @param style the style of control to construct. Default style is HORIZONTAL - * - * @exception IllegalArgumentException - *
    - *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • - *
- * @exception SWTException - *
    - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the parent
  • - *
- * @see SWT#HORIZONTAL - * @see SWT#VERTICAL - * @see Widget#getStyle - * - */ public RangeSlider(final Composite parent, final int style) { super(parent, SWT.DOUBLE_BUFFERED | ((style & SWT.BORDER) == SWT.BORDER ? SWT.BORDER : SWT.NONE)); - minimum = lowerValue = 0; - maximum = upperValue = 100; - increment = 1; - pageIncrement = 10; slider = new Image[] { SWTResourceManager.getImage(this.getClass(), "marker_l.png"), SWTResourceManager.getImage(this.getClass(), "marker_r.png")}; sliderHover = new Image[] { - SWTResourceManager.getImage(this.getClass(), "marker_l_lt.png"), - SWTResourceManager.getImage(this.getClass(), "marker_r_lt.png")}; + SWTResourceManager.getImage(this.getClass(), "marker_l_hover.png"), + SWTResourceManager.getImage(this.getClass(), "marker_r_hover.png")}; sliderDrag = new Image[] { - SWTResourceManager.getImage(this.getClass(), "marker_l_bl.png"), - SWTResourceManager.getImage(this.getClass(), "marker_r_bl.png")}; - sliderSelected = new Image[] { - SWTResourceManager.getImage(this.getClass(), "marker_l_bl_lt.png"), - SWTResourceManager.getImage(this.getClass(), "marker_r_bl_lt.png")}; - - vSlider = SWTResourceManager.getImage(this.getClass(), "h-slider-normal.png"); - vSliderHover = SWTResourceManager.getImage(this.getClass(), "h-slider-hover.png"); - vSliderDrag = SWTResourceManager.getImage(this.getClass(), "h-slider-drag.png"); - vSliderSelected = SWTResourceManager.getImage(this.getClass(), "h-slider-selected.png"); - - if ((style & SWT.VERTICAL) == SWT.VERTICAL) { - orientation = SWT.VERTICAL; - } else { - orientation = SWT.HORIZONTAL; - } + SWTResourceManager.getImage(this.getClass(), "marker_l_pressed.png"), + SWTResourceManager.getImage(this.getClass(), "marker_r_pressed.png")}; + Rectangle imgSize = slider[0].getBounds(); + minHeight =imgSize.height+2; + markerWidth = imgSize.width; + minimum = lowerValue = 0; + maximum = upperValue = 100; + increment = 1; + pageIncrement = 10; isSmooth = (style & SWT.SMOOTH) == SWT.SMOOTH; - isFullSelection = (style & SWT.CONTROL) == SWT.CONTROL; isHighQuality = (style & SWT.HIGH) == SWT.HIGH; isOn = (style & SWT.ON) == SWT.ON; - selectedElement = isFullSelection ? BOTH : LOWER; + selectedElement = NONE; addMouseListeners(); addListener(SWT.Resize, event -> { }); - addListener(SWT.FocusIn, e -> { - hasFocus = true; - redraw(); - }); - addListener(SWT.FocusOut, e -> { - hasFocus = false; - redraw(); - }); addListener(SWT.KeyDown, event -> { handleKeyDown(event); }); @@ -165,22 +86,37 @@ public class RangeSlider extends Canvas { @Override public int getStyle() { - return super.getStyle() | orientation | (isSmooth ? SWT.SMOOTH : SWT.NONE) | // + return super.getStyle() | (isSmooth ? SWT.SMOOTH : SWT.NONE) | // (isOn ? SWT.ON : SWT.NONE) | // (isFullSelection ? SWT.CONTROL : SWT.NONE) | // (isHighQuality ? SWT.HIGH : SWT.NONE); } - /** - * Add the mouse listeners (mouse up, mouse down, mouse move, mouse wheel) - */ private void addMouseListeners() { - addListener(SWT.MouseDown, event -> { - handleMouseDown(event); + addListener(SWT.MouseDown, e -> { + if (e.button == 1) { + selectKnobs(e); + if (upperHover || lowerHover) { + selectedElement = (lowerHover ? LOWER : NONE) + (upperHover ? UPPER : NONE); + startDragLowerValue = previousLowerValue = lowerValue; + startDragUpperValue = previousUpperValue = upperValue; + startDragPoint = new Point(e.x, e.y); + } + } }); - addListener(SWT.MouseUp, event -> { - handleMouseUp(event); + addListener(SWT.MouseUp, e -> { + if (selectedElement!=NONE) { + startDragPoint = null; + validateNewValues(e); + super.setToolTipText(clientToolTipText); + selectedElement=NONE; + redraw(); + } + }); + + addListener(SWT.MouseDoubleClick, event -> { + handleMouseDoubleClick(event); }); addListener(SWT.MouseMove, event -> { @@ -195,51 +131,15 @@ public class RangeSlider extends Canvas { handleMouseHover(event); }); - addListener(SWT.MouseDoubleClick, event -> { - handleMouseDoubleClick(event); + addMouseTrackListener(new MouseTrackAdapter() { + public void mouseExit(MouseEvent event) { + lowerHover = upperHover = false; + redraw(); + } }); + } - /** - * Code executed when the mouse is down - * - * @param e event - */ - private void handleMouseDown(final Event e) { - selectKnobs(e); - if (e.count == 1) { - priorSelectedElement = selectedElement; - } - if (upperHover || lowerHover) { - selectedElement = isFullSelection && lowerHover && upperHover ? BOTH : lowerHover ? LOWER : upperHover ? UPPER : selectedElement; - dragInProgress = true; - startDragLowerValue = previousLowerValue = lowerValue; - startDragUpperValue = previousUpperValue = upperValue; - startDragPoint = new Point(e.x, e.y); - } - } - - /** - * Code executed when the mouse is up - * - * @param e event - */ - private void handleMouseUp(final Event e) { - if (dragInProgress) { - startDragPoint = null; - validateNewValues(e); - dragInProgress = false; - super.setToolTipText(clientToolTipText); - } - } - - /** - * invoke selection listeners if either upper or lower value has changed. if - * listeners reject the change, restore the previous values. redraw if either - * upper or lower value has changed. - * - * @param e event - */ private void validateNewValues(final Event e) { if (upperValue != previousUpperValue || lowerValue != previousLowerValue) { if (!SelectionListenerUtil.fireSelectionListeners(this,e)) { @@ -248,18 +148,15 @@ public class RangeSlider extends Canvas { } previousUpperValue = upperValue; previousLowerValue = lowerValue; + increment = Math.max(1, (upperValue-lowerValue)/100); + pageIncrement = Math.max(1, (upperValue-lowerValue)/2); redraw(); } } - /** - * Code executed when the mouse pointer is moving - * - * @param e event - */ private void handleMouseMove(final Event e) { - if (!dragInProgress) { + if (selectedElement==NONE) { final boolean wasUpper = upperHover; final boolean wasLower = lowerHover; selectKnobs(e); @@ -267,75 +164,39 @@ public class RangeSlider extends Canvas { redraw(); } } else { // dragInProgress - final int x = e.x, y = e.y; - if (orientation == SWT.HORIZONTAL) { - if (selectedElement == BOTH) { - final int diff = (int) ((startDragPoint.x - x) / computePixelSizeForHorizontalSlider()) + minimum; - int newUpper = startDragUpperValue - diff; - int newLower = startDragLowerValue - diff; - if (newUpper > maximum) { - newUpper = maximum; - newLower = maximum - (startDragUpperValue - startDragLowerValue); - } else if (newLower < minimum) { - newLower = minimum; - newUpper = minimum + startDragUpperValue - startDragLowerValue; - } - upperValue = newUpper; - lowerValue = newLower; - if (!isSmooth) { - lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; - upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; - } - handleToolTip(lowerValue, upperValue); - } else if ((selectedElement & UPPER) != 0) { - upperValue = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; - if (!isSmooth) { - upperValue = Math.min(lowerValue, (int) (Math.ceil(upperValue / increment) * increment) - increment); - } - checkUpperValue(); - handleToolTip(upperValue); - } else { - lowerValue = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; - if (!isSmooth) { - lowerValue = Math.max(upperValue, (int) (Math.ceil(lowerValue / increment) * increment) - increment); - } - checkLowerValue(); - handleToolTip(lowerValue); + final int x = e.x; + if (selectedElement == BOTH) { + final int diff = (int) ((startDragPoint.x - x) / computePixelSizeForSlider()) + minimum; + int newUpper = startDragUpperValue - diff; + int newLower = startDragLowerValue - diff; + if (newUpper > maximum) { + newUpper = maximum; + newLower = maximum - (startDragUpperValue - startDragLowerValue); + } else if (newLower < minimum) { + newLower = minimum; + newUpper = minimum + startDragUpperValue - startDragLowerValue; } - } else { - if (selectedElement == BOTH) { - final int diff = (int) ((startDragPoint.y - y) / computePixelSizeForVerticalSlider()) + minimum; - int newUpper = startDragUpperValue - diff; - int newLower = startDragLowerValue - diff; - if (newUpper > maximum) { - newUpper = maximum; - newLower = maximum - (startDragUpperValue - startDragLowerValue); - } else if (newLower < minimum) { - newLower = minimum; - newUpper = minimum + startDragUpperValue - startDragLowerValue; - } - upperValue = newUpper; - lowerValue = newLower; - if (!isSmooth) { - lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; - upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; - } - handleToolTip(lowerValue, upperValue); - } else if ((selectedElement & UPPER) != 0) { - upperValue = (int) Math.round((y - 9d) / computePixelSizeForVerticalSlider()) + minimum; - if (!isSmooth) { - upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; - } - checkUpperValue(); - handleToolTip(upperValue); - } else { - lowerValue = (int) Math.round((y - 9d) / computePixelSizeForVerticalSlider()) + minimum; - if (!isSmooth) { - lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; - } - checkLowerValue(); - handleToolTip(lowerValue); + upperValue = newUpper; + lowerValue = newLower; + if (!isSmooth) { + lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; + upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; } + handleToolTip(lowerValue, upperValue); + } else if (selectedElement == UPPER) { + upperValue = (int) Math.round((x - 9d) / computePixelSizeForSlider()) + minimum; + if (!isSmooth) { + upperValue = Math.min(lowerValue, (int) (Math.ceil(upperValue / increment) * increment) - increment); + } + checkUpperValue(); + handleToolTip(upperValue); + } else if (selectedElement == LOWER){ + lowerValue = (int) Math.round((x - 9d) / computePixelSizeForSlider()) + minimum; + if (!isSmooth) { + lowerValue = Math.max(upperValue, (int) (Math.ceil(lowerValue / increment) * increment) - increment); + } + checkLowerValue(); + handleToolTip(lowerValue); } if (isOn) { validateNewValues(e); @@ -345,126 +206,48 @@ public class RangeSlider extends Canvas { } } - /** - * determine whether the input coordinate is within the scale bounds and between - * the current upper and lower values. - * - * @param x - * @param y - * @return - */ private boolean isBetweenKnobs(int x, int y) { - return orientation == SWT.HORIZONTAL ? x < coordUpper.x && x > coordLower.x && y >= minHeight/3 && y <= minHeight/3 + getClientArea().height - 2*minHeight/3 : // - y < coordUpper.y && y > coordLower.y && x >= minWidth/3 && x <= minWidth/3 + getClientArea().width - 2*minWidth/3; + return x < coordUpper.x && x > coordLower.x && y >= minHeight/3 && y <= minHeight/3 + getClientArea().height - 2*minHeight/3; } - /** - * set the upperHover and lowerHover values according to the coordinates of the - * input event, the key modifier state, and whether the style allows selection - * of both knobs. - * - * @param e - */ private void selectKnobs(final Event e) { if (coordLower == null) { return; } - final Image img = orientation == SWT.HORIZONTAL ? slider[0] : vSlider; + final Image img = slider[0]; final Rectangle imgBounds = img.getBounds(); final int x = e.x, y = e.y; lowerHover = x >= coordLower.x && x <= coordLower.x + imgBounds.width && y >= coordLower.y && y <= coordLower.y + imgBounds.height; upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && // x >= coordUpper.x && x <= coordUpper.x + imgBounds.width && // y >= coordUpper.y && y <= coordUpper.y + imgBounds.height; - lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover; - if (!lowerHover && !upperHover && isFullSelection && isBetweenKnobs(x, y)) { - lowerHover = upperHover = true; - } + lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover; + if (!lowerHover && !upperHover && isBetweenKnobs(x, y)) { + lowerHover = upperHover = true; + } } - /** - * if the input coordinate is within the scale bounds, return the corresponding - * scale value of the coordinate. otherwise return -1. - * - * @param x x coordinate value - * @param y y coordinate value - * @return - */ private int getCursorValue(int x, int y) { int value = -1; final Rectangle clientArea = getClientArea(); - if (orientation == SWT.HORIZONTAL) { - if (x < clientArea.width - 2*imgWidth && x >= imgWidth && y >= minHeight/3 && y <= clientArea.height - minHeight/3) { - value = (int) Math.round((x - 9d) / computePixelSizeForHorizontalSlider()) + minimum; - } - } else if (y < 9 + clientArea.height - 20 && y >= 9 && x >= 9 && x <= 9 + clientArea.width - 20) { - value = (int) Math.round((y - 9d) / computePixelSizeForVerticalSlider()) + minimum; + if (x < clientArea.width - 2*markerWidth && x >= markerWidth && y >= minHeight/3 && y <= clientArea.height - minHeight/3) { + value = (int) Math.round((x - 9d) / computePixelSizeForSlider()) + minimum; } return value; } - /** - * Code executed when the mouse double click - * - * @param e event - */ private void handleMouseDoubleClick(final Event e) { final int value = getCursorValue(e.x, e.y); if (value >= 0) { - selectedElement = priorSelectedElement; if (value > upperValue) { - if (selectedElement == BOTH) { - lowerValue += value - upperValue; - upperValue = value; - } else if ((selectedElement & UPPER) != 0) { - upperValue = value; - } else if ((selectedElement & LOWER) != 0) { - final int diff = upperValue - lowerValue; - if (value + diff > maximum) { - upperValue = maximum; - lowerValue = maximum - diff; - } else { - upperValue = value + diff; - lowerValue = value; - } - } + translateValues(value-upperValue); } else if (value < lowerValue) { - if (selectedElement == BOTH) { - upperValue += value - lowerValue; - lowerValue = value; - } else if ((selectedElement & LOWER) != 0) { - lowerValue = value; - } else if ((selectedElement & UPPER) != 0) { - final int diff = upperValue - lowerValue; - if (value - diff < minimum) { - lowerValue = minimum; - upperValue = minimum + diff; - } else { - upperValue = value; - lowerValue = value - diff; - } - } - } else if (value > lowerValue && value < upperValue && selectedElement != BOTH) { - if ((selectedElement & LOWER) != 0) { - lowerValue = value; - } else if ((selectedElement & UPPER) != 0) { - upperValue = value; - } + translateValues(value-lowerValue); } validateNewValues(e); } } - private StringBuffer toolTip; - private Point coordUpper; - private Point coordLower; - - /** - * set the tooltip if a toolTipFormatter is present. either one or two values - * are accepted. - * - * @param values - */ private void handleToolTip(int... values) { if (toolTipFormatter != null) { try { @@ -485,13 +268,8 @@ public class RangeSlider extends Canvas { } } - /** - * Code executed on mouse hover - * - * @param e event - */ private void handleMouseHover(final Event e) { - if (!dragInProgress && toolTipFormatter != null) { + if (selectedElement!=NONE && toolTipFormatter != null) { final int value = getCursorValue(e.x, e.y); if (value >= 0) { try { @@ -507,16 +285,6 @@ public class RangeSlider extends Canvas { } } - /** - * a formatter for displaying a tool tip when hovering over the scale and during - * thumb modification events. The - * {@link Format#format(Object, StringBuffer, java.text.FieldPosition)} method - * is invoked to retrieve the text for the tooltip where the input - * {@code Object} is an {@code Integer} with a value within the minimum and - * maximum. - * - * @param formatter - */ public void setToolTipFormatter(Format formatter) { toolTip = formatter != null ? new StringBuffer() : null; toolTipFormatter = formatter; @@ -527,13 +295,8 @@ public class RangeSlider extends Canvas { super.setToolTipText(clientToolTipText = string); } - /** - * Code executed when the mouse wheel is activated - * - * @param e event - */ private void handleMouseWheel(final Event e) { - if (selectedElement == NONE || dragInProgress) { + if (selectedElement == NONE) { e.doit = false; // we are consuming this event return; } @@ -563,41 +326,26 @@ public class RangeSlider extends Canvas { e.doit = false; // we are consuming this event } - /** - * Check if the lower value is in ranges - */ private void checkLowerValue() { if (lowerValue < minimum) { lowerValue = minimum; - } - if (lowerValue > (maximum-minThumbWidth)) { - lowerValue = (maximum-minThumbWidth); - } - if (lowerValue > (upperValue-minThumbWidth)) { - lowerValue = (upperValue-minThumbWidth); + } else if (lowerValue > (upperValue-thumbWidth)) { + lowerValue = (upperValue-thumbWidth); } } - /** - * Check if the upper value is in ranges - */ private void checkUpperValue() { - if (upperValue < (minimum+minThumbWidth)) { - upperValue = minimum+minThumbWidth; - } if (upperValue > maximum) { upperValue = maximum; - } - if (upperValue < (lowerValue+minThumbWidth)) { - upperValue = lowerValue+minThumbWidth; + } else if (upperValue < (lowerValue+thumbWidth)) { + upperValue = lowerValue+thumbWidth; } } - /** - * Draws the widget - * - * @param e paint event - */ + private float computePixelSizeForSlider() { + return (getClientArea().width - 2.0f*markerWidth) / (maximum - minimum); + } + private void drawWidget(final PaintEvent e) { final Rectangle rect = getClientArea(); if (rect.width == 0 || rect.height == 0) { @@ -605,50 +353,28 @@ public class RangeSlider extends Canvas { } e.gc.setAdvanced(true); e.gc.setAntialias(SWT.ON); - if (orientation == SWT.HORIZONTAL) { - drawHorizontalRangeSlider(e.gc); - } else { - drawVerticalRangeSlider(e.gc); - } - - } - - /** - * Draw the range slider (horizontal) - * - * @param gc graphic context - */ - private void drawHorizontalRangeSlider(final GC gc) { - drawBackgroundHorizontal(gc); + drawBackground(e.gc); if (lowerHover || (selectedElement & LOWER) != 0) { - coordUpper = drawHorizontalKnob(gc, upperValue, true); - coordLower = drawHorizontalKnob(gc, lowerValue, false); + coordUpper = drawMarker(e.gc, upperValue, true); + coordLower = drawMarker(e.gc, lowerValue, false); } else { - coordLower = drawHorizontalKnob(gc, lowerValue, false); - coordUpper = drawHorizontalKnob(gc, upperValue, true); + coordLower = drawMarker(e.gc, lowerValue, false); + coordUpper = drawMarker(e.gc, upperValue, true); } } - /** - * Draw the background - * - * @param gc graphic context - */ - private void drawBackgroundHorizontal(final GC gc) { + private void drawBackground(final GC gc) { final Rectangle clientArea = getClientArea(); - gc.setBackground(getBackground()); - //gc.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE));//getBackground()); gc.fillRectangle(clientArea); - if (isEnabled()) { gc.setForeground(getForeground()); } else { gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); } - gc.drawRoundRectangle(imgWidth, minHeight/3, clientArea.width - 2*imgWidth, clientArea.height - 2*minHeight/3, 3, 3); + gc.drawRoundRectangle(markerWidth, minHeight/3, clientArea.width - 2*markerWidth, clientArea.height - 2*minHeight/3, 3, 3); - final float pixelSize = computePixelSizeForHorizontalSlider(); + final float pixelSize = computePixelSizeForSlider(); final int startX = (int) (pixelSize * lowerValue); final int endX = (int) (pixelSize * upperValue); if (isEnabled()) { @@ -656,44 +382,24 @@ public class RangeSlider extends Canvas { } else { gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); } - gc.fillRectangle(imgWidth+startX, minHeight/3, endX - startX, clientArea.height - 2*minHeight/3); + gc.fillRectangle(markerWidth+startX, minHeight/3, endX - startX, clientArea.height - 2*minHeight/3); } - /** - * @return how many pixels corresponds to 1 point of value - */ - private float computePixelSizeForHorizontalSlider() { - return (getClientArea().width - 2.0f*imgWidth) / (maximum - minimum); - } - - /** - * Draws an horizontal knob - * - * @param gc graphic context - * @param value corresponding value - * @param upper if true, draws the upper knob. If - * false, draws the lower knob - * @return the coordinate of the upper left corner of the knob - */ - private Point drawHorizontalKnob(final GC gc, final int value, final boolean upper) { - final float pixelSize = computePixelSizeForHorizontalSlider(); + private Point drawMarker(final GC gc, final int value, final boolean upper) { + final float pixelSize = computePixelSizeForSlider(); int x = (int) (pixelSize * value); final int idx = upper?1:0; Image image; if (upper) { if (upperHover) { - image = dragInProgress || (selectedElement & UPPER) != 0 ? sliderDrag[idx] : sliderHover[idx]; - } else if ((selectedElement & UPPER) != 0 && !lowerHover) { - image = hasFocus ? sliderSelected[idx] : sliderHover[idx]; + image = (selectedElement & UPPER) != 0 ? sliderDrag[idx] : sliderHover[idx]; } else { image = slider[idx]; } } else { if (lowerHover) { - image = dragInProgress || (selectedElement & LOWER) != 0 ? sliderDrag[idx] : sliderHover[idx]; - } else if ((selectedElement & LOWER) != 0 && !upperHover) { - image = hasFocus ? sliderSelected[idx] : sliderHover[idx]; + image = (selectedElement & LOWER) != 0 ? sliderDrag[idx] : sliderHover[idx]; } else { image = slider[idx]; } @@ -710,120 +416,6 @@ public class RangeSlider extends Canvas { return new Point(x, getClientArea().height / 2 - slider[idx].getBounds().height / 2); } - /** - * Draw the range slider (vertical) - * - * @param gc graphic context - */ - private void drawVerticalRangeSlider(final GC gc) { - drawBackgroundVertical(gc); - drawBarsVertical(gc); - if (lowerHover || (selectedElement & LOWER) != 0) { - coordUpper = drawVerticalKnob(gc, upperValue, true); - coordLower = drawVerticalKnob(gc, lowerValue, false); - } else { - coordLower = drawVerticalKnob(gc, lowerValue, false); - coordUpper = drawVerticalKnob(gc, upperValue, true); - } - } - - /** - * Draws the background - * - * @param gc graphic context - */ - private void drawBackgroundVertical(final GC gc) { - final Rectangle clientArea = getClientArea(); - gc.setBackground(getBackground()); - gc.fillRectangle(clientArea); - - if (isEnabled()) { - gc.setForeground(getForeground()); - } else { - gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); - } - gc.drawRoundRectangle(9, 9, clientArea.width - 20, clientArea.height - 20, 3, 3); - - final float pixelSize = computePixelSizeForVerticalSlider(); - final int startY = (int) (pixelSize * lowerValue); - final int endY = (int) (pixelSize * upperValue); - if (isEnabled()) { - gc.setBackground(getForeground()); - } else { - gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); - } - gc.fillRectangle(9, 12 + startY, clientArea.width - 20, endY - startY - 6); - - } - - /** - * @return how many pixels corresponds to 1 point of value - */ - private float computePixelSizeForVerticalSlider() { - return (getClientArea().height - 20f) / (maximum - minimum); - } - - /** - * Draws the bars - * - * @param gc graphic context - */ - private void drawBarsVertical(final GC gc) { - if (isEnabled()) { - gc.setForeground(getForeground()); - } else { - gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); - } - } - - /** - * Draws a vertical knob - * - * @param gc graphic context - * @param value corresponding value - * @param upper if true, draws the upper knob. If - * false, draws the lower knob - * @return the coordinate of the upper left corner of the knob - */ - private Point drawVerticalKnob(final GC gc, final int value, final boolean upper) { - final float pixelSize = computePixelSizeForVerticalSlider(); - final int y = (int) (pixelSize * value); - - Image image; - if (upper) { - if (upperHover) { - image = dragInProgress || (selectedElement & UPPER) != 0 ? vSliderDrag : vSliderHover; - } else if ((selectedElement & UPPER) != 0 && !lowerHover) { - image = hasFocus ? vSliderSelected : vSliderHover; - } else { - image = vSlider; - } - } else { - if (lowerHover) { - image = dragInProgress || (selectedElement & LOWER) != 0 ? vSliderDrag : vSliderHover; - } else if ((selectedElement & LOWER) != 0 && !upperHover) { - image = hasFocus ? vSliderSelected : vSliderHover; - } else { - image = vSlider; - } - } - - if (isEnabled()) { - gc.drawImage(image, getClientArea().width / 2 - 8, y + 4); - } else { - final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE); - gc.drawImage(temp, getClientArea().width / 2 - 8, y + 4); - temp.dispose(); - } - return new Point(getClientArea().width / 2 - 8, y + 4); - } - - /** - * move the cursor location by the input delta values. - * - * @param xDelta - * @param yDelta - */ private void moveCursorPosition(int xDelta, int yDelta) { final Point cursorPosition = getDisplay().getCursorLocation(); cursorPosition.x += xDelta; @@ -831,162 +423,74 @@ public class RangeSlider extends Canvas { getDisplay().setCursorLocation(cursorPosition); } - /** - * Code executed when a key is typed - * - * @param event event - */ private void handleKeyDown(final Event event) { - // TODO consider API for setting accelerator values int accelerator = (event.stateMask & SWT.SHIFT) != 0 ? 10 : (event.stateMask & SWT.CTRL) != 0 ? 2 : 1; - if (dragInProgress) { + if (selectedElement != NONE) { switch (event.keyCode) { - case SWT.ESC: - startDragPoint = null; - upperValue = startDragUpperValue; - lowerValue = startDragLowerValue; - validateNewValues(event); - dragInProgress = false; - if (!isOn) { - redraw(); - } - event.doit = false; - break; - case SWT.ARROW_UP: - accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; - case SWT.ARROW_LEFT: - if (orientation == SWT.VERTICAL) { - moveCursorPosition(0, -accelerator); - } else { - moveCursorPosition(-accelerator, 0); - } - event.doit = false; - break; - case SWT.ARROW_DOWN: - accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; - case SWT.ARROW_RIGHT: - if (orientation == SWT.VERTICAL) { - moveCursorPosition(0, accelerator); - } else { - moveCursorPosition(accelerator, 0); - } - event.doit = false; - break; + case SWT.ESC: + startDragPoint = null; + upperValue = startDragUpperValue; + lowerValue = startDragLowerValue; + validateNewValues(event); + selectedElement = NONE; + if (!isOn) { + redraw(); + } + event.doit = false; + break; + case SWT.ARROW_UP: + accelerator = -accelerator; + case SWT.ARROW_LEFT: + moveCursorPosition(-accelerator, 0); + event.doit = false; + break; + case SWT.ARROW_DOWN: + accelerator = -accelerator; + case SWT.ARROW_RIGHT: + moveCursorPosition(accelerator, 0); + event.doit = false; + break; } return; } previousLowerValue = lowerValue; previousUpperValue = upperValue; - if (selectedElement == NONE) { - selectedElement = LOWER; - } switch (event.keyCode) { - case SWT.HOME: - if (selectedElement == BOTH) { - if ((event.stateMask & SWT.SHIFT) != 0) { - lowerValue = maximum - (upperValue - lowerValue); - upperValue = maximum; - } else { - upperValue = minimum + upperValue - lowerValue; - lowerValue = minimum; - } - } else if ((selectedElement & UPPER) != 0) { - upperValue = maximum; - } else { - lowerValue = minimum; - } - break; - case SWT.END: - if (selectedElement == BOTH) { - if ((event.stateMask & SWT.SHIFT) != 0) { - upperValue = minimum + upperValue - lowerValue; - lowerValue = minimum; - } else { - lowerValue = maximum - (upperValue - lowerValue); - upperValue = maximum; - } - } else if ((selectedElement & UPPER) != 0) { - upperValue = lowerValue; - } else { - lowerValue = upperValue; - } - break; - case SWT.PAGE_UP: - accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; - if (selectedElement == BOTH) { - translateValues(pageIncrement * -accelerator); - } else if ((selectedElement & UPPER) != 0) { - upperValue -= pageIncrement * accelerator; - } else { - lowerValue -= pageIncrement * accelerator; - } - break; - case SWT.PAGE_DOWN: - accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; - if (selectedElement == BOTH) { - translateValues(pageIncrement * accelerator); - } else if ((selectedElement & UPPER) != 0) { - upperValue += pageIncrement * accelerator; - } else { - lowerValue += pageIncrement * accelerator; - } - break; - case SWT.ARROW_DOWN: - accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; - case SWT.ARROW_RIGHT: - if (selectedElement == BOTH) { - translateValues(accelerator * increment); - } else if ((selectedElement & UPPER) != 0) { - upperValue += accelerator * increment; - } else { - lowerValue += accelerator * increment; - } - break; - case SWT.ARROW_UP: - accelerator = orientation == SWT.HORIZONTAL ? -accelerator : accelerator; - case SWT.ARROW_LEFT: - if (selectedElement == BOTH) { - translateValues(-accelerator * increment); - } else if ((selectedElement & UPPER) != 0) { - upperValue -= accelerator * increment; - } else { - lowerValue -= accelerator * increment; - } - break; - case SWT.TAB: - final boolean next = (event.stateMask & SWT.SHIFT) == 0; - if (next && (selectedElement & LOWER) != 0) { - selectedElement = isFullSelection && selectedElement == LOWER ? BOTH : UPPER; - redraw(); - } else if (!next && (selectedElement & UPPER) != 0) { - selectedElement = isFullSelection && selectedElement == UPPER ? BOTH : LOWER; - redraw(); - } else { - traverse(next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS); - } - return; + case SWT.HOME: + if ((event.stateMask & (SWT.SHIFT| SWT.CTRL)) == 0) { + upperValue = minimum + upperValue - lowerValue; + lowerValue = minimum; + } + break; + case SWT.END: + if ((event.stateMask & (SWT.SHIFT| SWT.CTRL)) == 0) { + lowerValue = maximum - (upperValue - lowerValue); + upperValue = maximum; + } + break; + case SWT.PAGE_UP: + translateValues(-accelerator * pageIncrement); + break; + case SWT.PAGE_DOWN: + translateValues( accelerator * pageIncrement); + break; + case SWT.ARROW_DOWN: + case SWT.ARROW_RIGHT: + translateValues( accelerator * increment); + break; + case SWT.ARROW_UP: + case SWT.ARROW_LEFT: + translateValues(-accelerator * increment); + break; } if (previousLowerValue != lowerValue || previousUpperValue != upperValue) { - if (selectedElement == BOTH) { - checkLowerValue(); - checkUpperValue(); - } else if ((selectedElement & UPPER) != 0) { - checkUpperValue(); - } else { - checkLowerValue(); - } + checkLowerValue(); + checkUpperValue(); validateNewValues(event); } } - /** - * translate both the upper and lower values by the input amount. The updated - * values are constrained to be within the minimum and maximum. The difference - * between upper and lower values is retained. - * - * @param amount - */ private void translateValues(int amount) { int newLower = lowerValue + amount; int newUpper = upperValue + amount; @@ -1001,336 +505,64 @@ public class RangeSlider extends Canvas { lowerValue = newLower; } - /** - * Adds the listener to the collection of listeners who will be notified when - * the user changes the receiver's value, by sending it one of the messages - * defined in the SelectionListener interface. - *

- * widgetSelected is called when the user changes the receiver's - * value. widgetDefaultSelected is not called. - *

- * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException - *
    - *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • - *
- * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * - * @see SelectionListener - * @see #removeSelectionListener - */ public void addSelectionListener(final SelectionListener listener) { checkWidget(); SelectionListenerUtil.addSelectionListener(this, listener); } - /** - * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean) - */ - @Override - public Point computeSize(final int wHint, final int hHint, final boolean changed) { - final int width, height; - checkWidget(); - if (orientation == SWT.HORIZONTAL) { - if (wHint < 100) { - width = 100; - } else { - width = wHint; - } - - if (hHint < minHeight) { - height = minHeight; - } else { - height = hHint; - } - } else { - if (wHint < minWidth) { - width = minWidth; - } else { - width = wHint; - } - - if (hHint < 100) { - height = 100; - } else { - height = hHint; - } - } - - return new Point(width, height); - } - - /** - * Returns the amount that the selected receiver's value will be modified by - * when the up/down (or right/left) arrows are pressed. - * - * @return the increment - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int getIncrement() { - checkWidget(); - return increment; - } - - /** - * Returns the 'lower selection', which is the lower receiver's position. - * - * @return the selection - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int getLowerValue() { - checkWidget(); - return lowerValue; - } - - /** - * Returns the maximum value which the receiver will allow. - * - * @return the maximum - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int getMaximum() { - checkWidget(); - return maximum; - } - - /** - * Returns the minimum value which the receiver will allow. - * - * @return the minimum - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int getMinimum() { - checkWidget(); - return minimum; - } - - /** - * Returns the amount that the selected receiver's value will be modified by - * when the page increment/decrement areas are selected. - * - * @return the page increment - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int getPageIncrement() { - checkWidget(); - return pageIncrement; - } - - /** - * Returns the 'selection', which is an array where the first element is the - * lower selection, and the second element is the upper selection - * - * @return the selection - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int[] getSelection() { - checkWidget(); - final int[] selection = new int[2]; - selection[0] = lowerValue; - selection[1] = upperValue; - return selection; - } - - /** - * Returns the 'upper selection', which is the upper receiver's position. - * - * @return the selection - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public int getUpperValue() { - checkWidget(); - return upperValue; - } - - /** - * Removes the listener from the collection of listeners who will be notified - * when the user changes the receiver's value. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException - *
    - *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • - *
- * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * - * @see SelectionListener - * @see #addSelectionListener - */ public void removeSelectionListener(final SelectionListener listener) { checkWidget(); SelectionListenerUtil.removeSelectionListener(this, listener); } - /** - * Sets the amount that the selected receiver's value will be modified by when - * the up/down (or right/left) arrows are pressed to the argument, which must be - * at least one. - * - * @param increment the new increment (must be greater than zero) - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public void setIncrement(final int increment) { + @Override + public Point computeSize(final int wHint, final int hHint, final boolean changed) { checkWidget(); - this.increment = increment; - redraw(); + final int width = Math.max(2*markerWidth+100, wHint); + final int height = Math.max(minHeight, hHint); + return new Point(width, height); } - /** - * Sets the 'lower selection', which is the receiver's lower value, to the input - * argument which must be less than or equal to the current 'upper selection' - * and greater or equal to the minimum. If either condition fails, no action is - * taken. - * - * @param value the new lower selection - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * @see #getUpperValue() - * @see #getMinimum() - * @see #setSelection(int, int) - */ - public void setLowerValue(final int value) { - setSelection(value, upperValue); + public int[] getSelection() { + checkWidget(); + return new int[] {lowerValue, upperValue}; } - /** - * Sets the maximum value that the receiver will allow. This new value will be - * ignored if it is not greater than the receiver's current minimum value. If - * the new maximum is applied then the receiver's selection value will be - * adjusted if necessary to fall within its new range. - * - * @param value the new maximum, which must be greater than the current minimum - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * @see #setExtrema(int, int) - */ + public int getIncrement() { + checkWidget(); + return increment; + } + + public int getMaximum() { + checkWidget(); + return maximum; + } + + public int getMinimum() { + checkWidget(); + return minimum; + } + + public int getPageIncrement() { + checkWidget(); + return pageIncrement; + } + +// public void setIncrement(final int increment) { +// checkWidget(); +// this.increment = increment; +// redraw(); +// } + public void setMaximum(final int value) { - setExtrema(minimum, value); + setLimits(minimum, value); } - /** - * Sets the minimum value that the receiver will allow. This new value will be - * ignored if it is negative or is not less than the receiver's current maximum - * value. If the new minimum is applied then the receiver's selection value will - * be adjusted if necessary to fall within its new range. - * - * @param value the new minimum, which must be nonnegative and less than the - * current maximum - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * @see #setExtrema(int, int) - */ public void setMinimum(final int value) { - setExtrema(value, maximum); + setLimits(value, maximum); } - /** - * Sets the minimum and maximum values that the receiver will allow. The new - * values will be ignored if either are negative or the min value is not less - * than the max. The receiver's selection values will be adjusted if necessary - * to fall within the new range. - * - * @param min the new minimum, which must be nonnegative and less than the max - * @param max the new maximum, which must be greater than the min - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public void setExtrema(final int min, final int max) { + public void setLimits(final int min, final int max) { checkWidget(); if (min >= 0 && min < max && (min != minimum || max != maximum)) { minimum = min; @@ -1349,73 +581,41 @@ public class RangeSlider extends Canvas { } } - /** - * Sets the amount that the receiver's value will be modified by when the page - * increment/decrement areas are selected to the argument, which must be at - * least one. - * - * @param pageIncrement the page increment (must be greater than zero) - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public void setPageIncrement(final int pageIncrement) { + public int getUpperValue() { checkWidget(); - this.pageIncrement = pageIncrement; - redraw(); + return upperValue; } - /** - * Sets the 'selection', which is the receiver's value. The lower value must be - * less than or equal to the upper value. Additionally, both values must be - * inclusively between the slider minimum and maximum. If either condition - * fails, no action is taken. - * - * @param value the new selection (first value is lower value, second value is - * upper value) - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- */ - public void setSelection(final int[] values) { + public void setUpperValue(final int value) { + setValues(lowerValue, value); + } + + public int getLowerValue() { + checkWidget(); + return lowerValue; + } + + public void setLowerValue(final int value) { + setValues(value, upperValue); + } + +// public void setPageIncrement(final int pageIncrement) { +// checkWidget(); +// this.pageIncrement = pageIncrement; +// redraw(); +// } + + public void setValues(final int[] values) { if (values.length == 2) { - setSelection(values[0], values[1]); + setValues(values[0], values[1]); } } - /** - * Sets the 'selection', which is the receiver's value. The lower value must be - * less than or equal to the upper value. Additionally, both values must be - * inclusively between the slider minimum and maximum. If either condition - * fails, no action is taken. - * - * @param lowerValue the new lower selection - * @param upperValue the new upper selection - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * @see #getMinimum() - * @see #getMaximum() - */ - public void setSelection(final int lowerValue, final int upperValue) { - setSelection(lowerValue, upperValue, false); + public void setValues(final int lowerValue, final int upperValue) { + setValues(lowerValue, upperValue, false); } - public void setSelection(final int lowerValue, final int upperValue, boolean update) { + + public void setValues(final int lowerValue, final int upperValue, boolean update) { checkWidget(); if (lowerValue <= upperValue && lowerValue >= minimum && upperValue <= maximum && (this.lowerValue != lowerValue || this.upperValue != upperValue)) { this.lowerValue = lowerValue; @@ -1429,27 +629,4 @@ public class RangeSlider extends Canvas { redraw(); } } - - /** - * Sets the 'upper selection', which is the upper receiver's value, to the input - * argument which must be greater than or equal to the current 'lower selection' - * and less or equal to the maximum. If either condition fails, no action is - * taken. - * - * @param value the new upper selection - * - * @exception SWTException - *
    - *
  • ERROR_WIDGET_DISPOSED - if the receiver has been - * disposed
  • - *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the - * thread that created the receiver
  • - *
- * @see #getLowerValue() - * @see #getMaximum() - * @see #setSelection(int, int) - */ - public void setUpperValue(final int value) { - setSelection(lowerValue, value); - } } \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java index ecca946..3bac523 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java @@ -64,18 +64,18 @@ public class TimeZoomScrollbar extends Composite { @Override public void widgetSelected(SelectionEvent e) { int[] value = timeSlider.getSelection(); - int diff = value[1]-value[0]; - int newLow = Math.max(0, value[0]-Math.max(1, diff/10)); - timeSlider.setSelection(newLow, newLow+diff, true); + int incr=timeSlider.getIncrement(); + int lower = Math.max(timeSlider.getMinimum(), value[0]-incr); + timeSlider.setValues(lower, lower + (value[1]-value[0]), true); } }); rightButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int[] value = timeSlider.getSelection(); - int diff = value[1]-value[0]; - int newHigh = Math.min(timeSlider.getMaximum(), value[1] + diff/10); - timeSlider.setSelection(newHigh-diff, newHigh, true); + int incr=timeSlider.getIncrement(); + int upper = Math.min(timeSlider.getMaximum(), value[1]+incr); + timeSlider.setValues(upper - (value[1]-value[0]), upper, true); } }); @@ -104,7 +104,7 @@ public class TimeZoomScrollbar extends Composite { } public void setSelection(int[] sel) { assert(sel.length==2); - timeSlider.setSelection(sel[0], sel[1]); + timeSlider.setValues(sel[0], sel[1]); } public int[] getSelection() { return timeSlider.getSelection(); @@ -112,12 +112,6 @@ public class TimeZoomScrollbar extends Composite { public void addSelectionListener(SelectionListener selectionListener) { timeSlider.addSelectionListener(selectionListener); } - public void setIncrement(int value) { - timeSlider.setIncrement(value); - } - public void setPageIncrement(int value) { - timeSlider.setPageIncrement(value); - } public void setMinimum(int value) { timeSlider.setMinimum(value); } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-drag.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/h-slider-drag.png deleted file mode 100644 index 2011d9b40b5cafb987a58f3af01a9333f3905fce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1057 zcmeAS@N?(olHy`uVBq!ia0vp^f5hcz=sfi_-`FRQA=g;4G z^F4Xp-d-vn-?nmE0{``CV`Oh!E{#|)Y>t zcRv2Ubm`KMKmVS7`SakxgXq?!XKp?D_4i*$-Mnw#zHK^o73iH&Fd71shd_Aha}%H` zj3q&S!3+-1ZlnP@v7RoDAr-fh6Amz#g>5QO&^>hM)PaP&#H1DLSFc^UZjp+*-WgVr zNn1@!jV@ficqt%s+H`>jPm>(Q0w;((d6wcPI8o@)!vv@B!{<8E_^hR8#s0}r_&!7V ej`A^f5eA09t-?MpMSGru-0tb>=d#Wzp$Pyk5hcz=sfi_-`FRQRdO?fI8VrJbhi+Z*%hqsp)k# z8VUe~I14-?iy0XB4uLSEsD@VqP>?0v(btiIVPik{pF~y$24;o;pAgso|Np;u_qluR z(Z#Da+`4t^=g*%{-+ZcDdT8?Q>waaEC(l|iZSRej-~RZNOnmX-ThprJufF}=`rx~F z@x&PmmOXp+tY^!`nfq_P{{DBzqo3>U{Rpd@ef8>9oBEA!zW?3z_}8WfKhK{(|Mthf zZI6Dx`|)qrlRszAp8fj!-;MWwzWx4p`{SSQfBxP3^ykN)e~&)@dHUt=&p-d3fBk#u z(xsn&|GoV7_rZe)8FLO@c=-0$-+zfycYpi#ZO4VjK#z=q(GZ|k2pl}0t_(Dbu_VYZ zn8D%MjWi%9*3-o?q~ca`!U2XbF{1(n)iZ}q9Z1MZTe5!f;-w3ht5hcz=sfi_-`FRQXI+2kK-m@$_|Nzs=1fq^AF` zjj;_V#981GS*8o|0J?9FfcO&_=LFr|NsB(+qX-W zELpj7<*i${e*XOV`t|EMbLMQ?v?(_?cjnBQTefWZ{P}ZscJ{k>?-njx_~px&>({Sm zWo6BqH}BcAXRBAQ-nMPq&6_u`T)9$OT6*>B)q;Y8uV24jyLRpT`SWMbp8fUf*PAzQ ze*gac{{8z8A3l8i`0>)EOMm|S`Sj`2g9i^LOqg)@?%mGL&Trqooj!dU=*Uqp8UpkT zfpaT@Y=QPMmIV0)GdMiEkp|>Md%8G=RNP8VIKWV4b*Vr>^UR@B2No<{yN-p0i_6H! zD9I_tK{2zGH&is$&eg2YQH(J!PERaFFtU&_&o50xkke6)Pp!oCO;5(N4VxF5hcz=sfi_-`FRQKieMtHhuDU*ONas@BiL-|Ht;@-`gMm*nRqY@6#Xq&wn3%{$u~;@6#`T z9lrj3{`IfJx4$pH{mqzj$l=Z#$M1i4TzCw0)hHMZfdLEw{km1EKBqYnY0CqjQi+2Y!DI$yzVcPf2Xhze-h5E$p^*vnGxR57bPmj-+ znv>yh_^MVb83XcP_@0@oQGZHFwpi34>G%7oQcASe zl4Y69W;6MoOk@m5-0SsTMx)UKGh?&az&QtF4EEjw0HW!1Dy>!vd7dML0BbFn8C6;0 zr`tswMG@xnIhYyN+8X(i001!nXsuzb1rdRnVT=L1$JGH8MFAp02m#JH5D^;QxsBYyw^b5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi z!vFvd!vV){sAK>D0Sie)K~yMHb&*R-#6S>+E05ktz@6JhglrADKrRpv(F=Hlge2xP zZez=u78|wgMXQG{x{g$^V5sL zFReL036|&i=6E>B>Bf_DZ3&iT*|sPO`LW;2>H1c#SFkiqU&Anb9LEua5FjTB8emD1 zY=R(o7>0qGqHO`>FTmnB-uk|O-*p|ds?jtJoq!He6zyEsz0*Y$IuL*kob#|OOPX5i zQ$gf_JL|e$rd8Jv0e#<7f)EPtv_`Mc4(mzEmHu_mFga)di&a&fKtgF*flVz9x9Y@~ uv>nF*&-1{xZ7@v}EXyKY7>4@uBm4m5xA1jwJj6k-xI4^0QUsaVJK80n@3UHw_PMB<{5CKY;PrFXnUZ zLx5dnwQqbcyuSM7WWpT~RN1Tr$GihZBflCBxm~YGrO>Kkn}T5={k~s6J#+KEB9(%v zLe7Lu!DvAS1Fql3WK}2y&$;uqY+uwhaW*4u!>Z)PHbXelDN3tfesAR-8Ezy(;?*w~5NaTTf3r3oPbT{DP)8gv2_khUdM z710b=0~Op1iV}7&>Y5~i_ZC+Jv>(~FgldVXQu@$U@Hik+K$@0V*IPiOHz+QKb;@5QX8l38IUXCN&io-~=2Ybt)eMo8#mFAms)$xdjptm5X3jFYmxm+*|140N$DS??M007L45CWKa1VfAysOuWc z3=u&H0bSQYLzn;&ji7B?hzMfSOu$+@#=h_2y+?Fz0?s*j@6j|3VvMNk8fe=aIGs*d iuh(~vnUtW1H~auKJ?_B$=(TGA0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0TxL_K~yMHb&g9) z#6S>+D-*JlQ34SHAp`0G#$}F>Wke-w50TehT&m+0Jc1|4GK+wV0m=KFwB2PoWCRO7 z(w+LM{)YeR6E4q2VK;2%``?m2yr*YjcOlOAlahiUc>9WDGTq#g`QK8K@B4=+ipclz zNT%!ki6D8N_a25JiRm@m>@Zh^J-bvgCGddG!4>H zfCg-6^I)3h{Wy+L*Y$66-ayy}!!YjpzF#Jp#6^r4h5^d5gsQ3#-eg~lVAJa+KQ~OE z#bi}zYxg(cIK(r7^??S8sA*9R_rV7(!1KB|m2|{)tVw~0{h1ImKK(G@+ z7@ZUoAE2K0`_E|(T$pdJ^u}vvr3+s9dU|~I+O~Wa<2e3YEtmPW+sn`6YLyS)-cN!( z4hDn#q2JH9-CkZg!jCA5?nk2$)9IA!Rto_C7$=hnh&V`2kSaxPKo?O{?G;kz z0(3b-N+>80a^(gId)MCe?lQJE1;G@MkzO@l@ic>i^uyC5|I7&B`{Vr+c(^MRBz-)l z#bWVw7b!^2m{e8OeWW0jheIlgB9&!%ixi}Mw@cgYHf=VW8-FwbXqpBuf{0MpHS_uW z6=1nszD)qEwS=xCgn;)RW6TAOG6m^*wW1Xv#z^-Er_(93+3b9W+SEAbu-2lrMr%!; z=VV!S?%Dr1ALXPy79zU!Mup`Uom>-v9sr07*qoM6N<$f+ydO AjQ{`u delta 331 zcmV-R0kr z)b|qM^g=!s3mJ_@PkW(oaxU-lxlE^184ib&T_}+tXsxj!(0}Xou0u&+{$d*J+F)j$@L|k%jjdW3~osEsaKll_ASm?o=3K zXti1^Kr4lE?nIBFEX#F8mXZAcHd&VC>XRzV_*`#o^v*e|sv;qZNZV}=MeyF^y(ff# dbB<=S$u~>H`|M})O$`75002ovPDHLkV1g8Xo0k9p diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl.png deleted file mode 100644 index 558f9bd8c979be89c1625127ce3c88847c45428f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 386 zcmV-|0e$|7P)4f26vgrXz4OLqBLrMTNU@MMm93-=1QJ3NY^*IqAR(}wsQ5XoB?JU3KZC7>ogW|s z=IuD^%;ep7pG7tSC7$LqzjMekvu`|J<3CZEtyf>?uRj9yy}~!2mLK1Lmihe6`F%)B zE{vnHzyIpx+1cAq|02bqX$HCuwzr?ZI6Zy$*OTIf*d$^!77Jl(Ywz&ns8srfDiRHg*q=k3W0{>Oh7?bbcG8R4{|<>x#99J9|e*`X%6nc2QVbAtfOtNJ%hz zz;ya-H{j4lq0352U?wXlOeRVwE_AKZW?e0XWP&AS7?gm+uePG~KuSW+f|+7T==&Au zmx0a#W`boUo09$Zp+Mi&EInYRxZeOT$}m<0Tp0VBKG$Tw0bZ0+lyRsCRGBBUOD3fv gyWm;w`qA`?KQM~Ctzq%VNdN!<07*qoM6N<$f*$CpmjD0& diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl_lt.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_bl_lt.png deleted file mode 100644 index e37e735e502b7acb6e1d625a46287de40c4b4d20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmV-!0g?WRP)j!H;O&wemz9dZ^@hMa_yU~KfAPw6 M07*qoM6N<$f{SaUu>b%7 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_hover.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8b3696e2d53ae3c289fb1fd31d71daeb750c2052 GIT binary patch literal 326 zcmV-M0lEH(P)PHzF`^ZDHXAclaNp{l4VB62{z zBA1oDzdR9hMpeoCJ{%4ijYjkUM1&9mAq1RrIOnMAnxZI<8A3{^DltZK&cqn`3F&q_ z!hV=iBF6X!I7i%vJe*1?9f61-UH5D0y+4A_wq>XKv+&*{BHzG#iG~f_AQAk{u*_uvWL=5?n#b6ay&&HjeY-yYF3# ziNk>L!r>O@I~UHyo1wgOcFaE$nc->tmOefKM+b>;d8OMd)5T)(d=Ls3BmLOzbhFv$ zd_I5q1BLUEZnI3YEYtORt!bLRb|H%@bzS3uIF6akW_PM;mdoV>;4BJtRUtqK0b>l) z>GW1r&1$u}x4OR|fcL)DWHPw{B8w_jRpC_e-V;J-q49WpZBZ!85&=Y{HAMsw!Gcni zCEu!u2qA>lG{!V7ilS(NZaPU4ECGt5pzb7p6-7~V;VaLnLclqPh_t)c>oq|BnN#@2 r=xQ(+UopbyE9pCRGGRBm-00000NkvXXu0mjf^cIxB diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_pressed.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/marker_r_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..e602b5660e84fd1b4a3d095fad9fbd405d3d716c GIT binary patch literal 349 zcmV-j0iyniP)dR^>1onXQy|fTaEq)wd{f|n zP{>HreVTKI?_lut&RvIpCJY8y>+SjJ1&FVTdN}swcI&6p>FZTg566C56n?+oUq|(D z?C(b-Kby^bS(blL1mJo-7K;VWIVO`y4ltk3AA!#ZAaRawYgsOrq-lDAB7p4XmfC2H zF|1ZAoO2XKkpp1_&`A>lYca+kB5XDrk|ZI|^M_-HEF-iQt@UYlyB+<0|5!40jzAwH zwALu4P)eP@NSz~UBH}p47;_1-ZkJFgMC249B4=RRZKUZSA}FQMT5~uYnhRM*+ literal 0 HcmV?d00001 diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-drag.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-drag.png deleted file mode 100644 index 2d88c1afbd14dea934b22941e9beda11fe12abb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1085 zcmeAS@N?(olHy`uVBq!ia0vp^AhsX}GmyOe_w02brB~t_QQ};bnpl#VpQjL#nVZT` zoS3VpU}&U}mtUr*U}Ruus9#HaCxutg6yO z_60y8&H|6fVg?4jLmgEw{G3~`Sa(Km+wlZtf^hJ$2Fy9;`BKUOZT0B{MI?S`q|r$l`}UsF57?c>4%ub zC!G?jrp;aW?Af#C#k*Tp9J>7cQ|g*a0SnLg=C)qFdQ~T>``W87S(|P~t-5;t{P`Pi zz9(z`#ezr6nbcf-AJ?|%H<{pkD0pMQ@(|M}(Dze{g^ef$0I z&d1-EE?xTZ=ik#We;zz|5Z$`;%&jNC{{9Q8oA>S8w@t^c0=+W|Mniz|5C~6wZUQug zu_VYZn8D%MjWi&q($mE;q~ezBvD-pU0TK-t_h0Jd3lYvTtG?hd$z;~rW54ag_g%X> z>7K@nxFaR{w)Tp;6L8^A*PJx*6cf*h7c{O#9lv;C zv3$#NgAeDGX0Lty)~38(VB*a?k(SxFC;b=qzC9~QvRC~L`~4fjKHbZ!3_#HaCxutoSRl zFa@9xXMsm#F#`kNArNL1)$nQn3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XN>+|Nj^7K6kG@ zx_H%wTeoig{Q2|gn@@F14^7^E-LGu&u)wjP}AAI*N zo;YK{vS-hp^=!E~bN|iP-~aA-^mE<4A7OQ~uU@@sQ@`=e_rJRy|JwB6=lS#J-~RZw z?a}XdKmP4{^5^W?vtNJzyYc?dx8MJ6fBf_P&%b-0{`~m!@6qQ!Prv;A`RCvBuYWIH zy7cq!zn9oVw+6e2tfeOw;3CY_U_V zu!Pw!{o&7f9C{4ftP2I)uebfYSNN8fJA3Q1f0MF=mMru=Zv*n1r>mdKI;Vst00{B; A;s5{u diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-normal.png b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/slider-normal.png deleted file mode 100644 index 4c5098ca95cb10882ccfe36902fac9a8de247103..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1072 zcmeAS@N?(olHy`uVBq!ia0vp^AhsX}GmyOe_w02brB~t_QQ};bnpl#VpQjL#nVZT` zoS3VpU}&U}mtUr*U}Ruus9PU}#{lVd@EapicG@PhVH|+uS@tvK;Al z(N}>&oCO|{#S9F5hd`K7RKu$QD9DoT=wtDsIZQHipym|A=l`EyCrB|C>lyjvNJ}AwbU% zIJY9m7HA)1NswPKgTu2MX+Tbnr;B4q#Vyri(R@t?BCH3L!veY@RDwJ+4><<~^ZbsV zH|O?GsW%q`?=ysN;i+?XWdL(wZ7v`&G9Yemb}k??FflP8F*!OgHaamgAS*C2FfbqQ{ks4F00(qQ zO+^RW3k(tqC(w7(TL1t632;bRa{vGi!vFvd!vV){sAK>D00d`2O+f$vv5yP`8-0VU3{kYKMw+mZv00001bW%=J06^y0W&i*HY)M2x zRCwAg#?cl+KmbM2TP7hij3h~tM*jZ?bFB8$*5WPvBKi4?*-Li%V6tn+H%2 state) { Integer waves = state.containsKey(SHOWN_WAVEFORM+"S") ? Integer.parseInt(state.get(SHOWN_WAVEFORM + "S")):0; //$NON-NLS-1$ //$NON-NLS-2$ List trackEntries = new LinkedList<>(); + List selectedTrackEntries = new LinkedList<>(); for (int i = 0; i < waves; i++) { IWaveform waveform = database.getStreamByName(state.get(SHOWN_WAVEFORM + i)); if (waveform != null) { TrackEntry trackEntry = waveformPane.addWaveform(waveform, -1); //check if t is selected - boolean isSelected = Boolean.parseBoolean(state.get(SHOWN_WAVEFORM + i + WAVEFORM_SELECTED)); - if(isSelected) { - trackEntry.selected = true; - } else { - trackEntry.selected = false; - } trackEntries.add(trackEntry); + if(Boolean.parseBoolean(state.get(SHOWN_WAVEFORM + i + WAVEFORM_SELECTED))) + selectedTrackEntries.add(trackEntry); String v = state.get(SHOWN_WAVEFORM + i + VALUE_DISPLAY); if(v!=null) trackEntry.valueDisplay=ValueDisplay.valueOf(v); @@ -856,6 +853,8 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis } catch (NumberFormatException e) { } } + ISelection sel = new StructuredSelection(selectedTrackEntries); + waveformPane.setSelection(sel); updateAll(); } From 24890f9bbb835e95757af6cab8a007e214f80c35 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 6 Jan 2022 19:15:31 +0100 Subject: [PATCH 6/8] change behavior with a clear distinction If no modifier key is used the zoombar acts as a scroll bar. If ctrl is used it modifies the zoom level, shift is a speed modifier --- .../ui/swt/internal/WaveformView.java | 2 +- .../ui/swt/internal/slider/RangeSlider.java | 69 ++++++++++++------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 755af81..11cdd0f 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -205,7 +205,7 @@ public class WaveformView implements IWaveformView { long endTime = waveformCanvas.getTimeForOffset(end.x); if(startTime { if (e.button == 1) { selectKnobs(e); - if (upperHover || lowerHover) { - selectedElement = (lowerHover ? LOWER : NONE) + (upperHover ? UPPER : NONE); + selectedElement = (lowerHover ? LOWER : NONE) | (upperHover ? UPPER : NONE); + if (selectedElement!=NONE) { + if((e.stateMask & SWT.CTRL)==0) + selectedElement=BOTH; startDragLowerValue = previousLowerValue = lowerValue; startDragUpperValue = previousUpperValue = upperValue; startDragPoint = new Point(e.x, e.y); @@ -112,6 +114,16 @@ public class RangeSlider extends Canvas { super.setToolTipText(clientToolTipText); selectedElement=NONE; redraw(); + } else { + if(e.xcoordUpper.x+markerWidth) { + translateValues(pageIncrement); + validateNewValues(e); + redraw(); + } } }); @@ -211,20 +223,18 @@ public class RangeSlider extends Canvas { } private void selectKnobs(final Event e) { - if (coordLower == null) { - return; + if (coordLower != null) { + final Rectangle imgBounds = slider[0].getBounds(); + final int x = e.x, y = e.y; + lowerHover = x >= coordLower.x && x <= coordLower.x + imgBounds.width && y >= coordLower.y && y <= coordLower.y + imgBounds.height; + upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && // + x >= coordUpper.x && x <= coordUpper.x + imgBounds.width && // + y >= coordUpper.y && y <= coordUpper.y + imgBounds.height; + lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover; + if (!lowerHover && !upperHover && isBetweenKnobs(x, y)) { + lowerHover = upperHover = true; + } } - final Image img = slider[0]; - final Rectangle imgBounds = img.getBounds(); - final int x = e.x, y = e.y; - lowerHover = x >= coordLower.x && x <= coordLower.x + imgBounds.width && y >= coordLower.y && y <= coordLower.y + imgBounds.height; - upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && // - x >= coordUpper.x && x <= coordUpper.x + imgBounds.width && // - y >= coordUpper.y && y <= coordUpper.y + imgBounds.height; - lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover; - if (!lowerHover && !upperHover && isBetweenKnobs(x, y)) { - lowerHover = upperHover = true; - } } private int getCursorValue(int x, int y) { @@ -296,14 +306,10 @@ public class RangeSlider extends Canvas { } private void handleMouseWheel(final Event e) { - if (selectedElement == NONE) { - e.doit = false; // we are consuming this event - return; - } previousLowerValue = lowerValue; previousUpperValue = upperValue; - final int amount = increment * ((e.stateMask & SWT.SHIFT) != 0 ? 10 : (e.stateMask & SWT.CTRL) != 0 ? 2 : 1); - if (selectedElement == BOTH) { + final int amount = Math.max(1, ((e.stateMask & SWT.SHIFT) != 0 ? (upperValue-lowerValue)/6 : (upperValue-lowerValue)/15)); + if ((e.stateMask&SWT.CTRL)==0) { int newLower = lowerValue + e.count * amount; int newUpper = upperValue + e.count * amount; if (newUpper > maximum) { @@ -315,12 +321,23 @@ public class RangeSlider extends Canvas { } upperValue = newUpper; lowerValue = newLower; - } else if ((selectedElement & LOWER) != 0) { - lowerValue += e.count * amount; - checkLowerValue(); } else { - upperValue += e.count * amount; - checkUpperValue(); + int newLower = lowerValue + e.count * amount/2; + int newUpper = upperValue - e.count * amount/2; + int dist = newUpper - newLower; + if (newUpper > maximum) { + newUpper = maximum; + newLower = maximum - dist; + } else if (newLower < minimum) { + newLower = minimum; + newUpper = minimum + dist; + } + if(newUpper<=newLower) { + newLower=lowerValue + (upperValue - lowerValue)/2; + newUpper=newLower+1; + } + upperValue = newUpper; + lowerValue = newLower; } validateNewValues(e); e.doit = false; // we are consuming this event From 20934a9f47388248babfd7842ad81d789a013826 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 7 Jan 2022 19:42:27 +0100 Subject: [PATCH 7/8] fix behavior of ZoomBar used by WaveformCanvas --- .../ui/swt/internal/WaveformCanvas.java | 50 +++++++++---------- .../ui/swt/internal/WaveformView.java | 8 +-- .../ui/swt/internal/slider/RangeSlider.java | 40 ++++----------- .../{TimeZoomScrollbar.java => ZoomBar.java} | 6 +-- 4 files changed, 42 insertions(+), 62 deletions(-) rename plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/{TimeZoomScrollbar.java => ZoomBar.java} (96%) diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java index 5f7cde9..ec07c38 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java @@ -46,7 +46,7 @@ import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.ZoomKind; import com.minres.scviewer.database.ui.swt.Constants; -import com.minres.scviewer.database.ui.swt.internal.slider.TimeZoomScrollbar; +import com.minres.scviewer.database.ui.swt.internal.slider.ZoomBar; public class WaveformCanvas extends Canvas implements IWaveformZoom{ @@ -54,6 +54,8 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public static final long ZOOM_FULL = -1; + private static final int INITIAL_ZOOM_BAR_MAX = 1000; + private boolean doubleBuffering = true; IWaveformStyleProvider styleProvider; @@ -82,22 +84,17 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ private List cursorPainters; - private TimeZoomScrollbar horizontal; + private ZoomBar horizontal; private int[] lastHorSelection; + private long sliderScaleFactor = 1; + private ScrollBar vertical; HashMap wave2painterMap; - /** - * Constructor for ScrollableCanvas. - * - * @param parent - * the parent of this control.super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL); - * @param style - * the style of this control. - */ - public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider, TimeZoomScrollbar.IProvider scrollbarProvider) { + + public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider, ZoomBar.IProvider scrollbarProvider) { super(parent, (style & ~SWT.H_SCROLL) | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL ); this.styleProvider=styleProvider; addControlListener(new ControlAdapter() { /* resize listener. */ @@ -158,10 +155,6 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void setOrigin(int x, int y) { checkWidget(); -// if(x<=0) horizontal.setSelection(-x); -// x = -horizontal.getSelection()[0]; -// if(y<=0) vertical.setSelection(-y); -// y = -vertical.getSelection(); origin.x = x; origin.y = y; syncSb(); @@ -174,6 +167,12 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void setMaxTime(long maxTime) { this.maxTime = maxTime; + if(maxTime>INITIAL_ZOOM_BAR_MAX) { + long maxBarTime = maxTime; + while(maxBarTime>Integer.MAX_VALUE) maxBarTime/=1000; + horizontal.setMaximum((int) maxBarTime); + } + sliderScaleFactor = maxTime/horizontal.getMaximum(); syncSb(); } @@ -302,22 +301,22 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ public void widgetSelected(SelectionEvent event) { if (!painterList.isEmpty()) { int[] sel = horizontal.getSelection(); - long lowerTime = sel[0]*maxTime/horizontal.getMaximum(); - long upperTime = sel[1]*maxTime/horizontal.getMaximum(); + long lowerTime = sel[0]*sliderScaleFactor; + long upperTime = sel[1]*sliderScaleFactor; if(sel[1]-sel[0] != lastHorSelection[1]-lastHorSelection[0]) { long time_diff = upperTime-lowerTime; long factor = time_diff/getClientArea().width; setScalingFactor(factor, lowerTime+time_diff/2); } else { - origin.x = -(int) (lowerTime / getScale()); - event.widget.getDisplay().asyncExec(() -> {redraw();}); + origin.x = -(int) (lowerTime/getScale()); + WaveformCanvas.this.getDisplay().asyncExec(() -> {redraw();}); } lastHorSelection=sel; } } }); horizontal.setMinimum(0); - horizontal.setMaximum(10000); + horizontal.setMaximum(INITIAL_ZOOM_BAR_MAX); lastHorSelection = horizontal.getSelection(); vertical.setEnabled(false); @@ -328,7 +327,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ if (!painterList.isEmpty()) { origin.y=-vertical.getSelection(); fireSelectionEvent(); - event.widget.getDisplay().asyncExec(() -> {redraw();}); + WaveformCanvas.this.getDisplay().asyncExec(() -> {redraw();}); } } }); @@ -345,7 +344,7 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ syncVSb(); fireSelectionEvent(); } - this.getDisplay().asyncExec(() -> {redraw();}); + redraw(); } private void syncVSb() { @@ -373,10 +372,9 @@ public class WaveformCanvas extends Canvas implements IWaveformZoom{ horizontal.setEnabled(wave2painterMap.size()>0); Rectangle clientArea=getClientArea(); int clientWidth = clientArea.width; - if(maxTime>0) { - int lower = (int) ( -origin.x * getScale() * horizontal.getMaximum() / maxTime); - int upper = (int) ((clientWidth-origin.x) * getScale() * horizontal.getMaximum() / maxTime); - int[] curSel = horizontal.getSelection(); + if(sliderScaleFactor>0) { + int lower = (int) ( ( -origin.x * getScale()) / sliderScaleFactor); + int upper = (int) (((clientWidth-origin.x) * getScale()) / sliderScaleFactor); lastHorSelection = new int[] {Math.max(lower,0), Math.min(upper, horizontal.getMaximum())}; horizontal.setSelection(lastHorSelection); } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 11cdd0f..ae2347a 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -91,7 +91,7 @@ import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; -import com.minres.scviewer.database.ui.swt.internal.slider.TimeZoomScrollbar; +import com.minres.scviewer.database.ui.swt.internal.slider.ZoomBar; public class WaveformView implements IWaveformView { @@ -352,11 +352,11 @@ public class WaveformView implements IWaveformView { gl_waveformPane.marginHeight = 0; waveformPane.setLayout(gl_waveformPane); - waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider, new TimeZoomScrollbar.IProvider() { + waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider, new ZoomBar.IProvider() { @Override - public TimeZoomScrollbar getScrollBar() { - TimeZoomScrollbar timeSliderPane = new TimeZoomScrollbar(waveformPane, SWT.NONE); + public ZoomBar getScrollBar() { + ZoomBar timeSliderPane = new ZoomBar(waveformPane, SWT.NONE); GridData gd_timeSliderPane = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1); timeSliderPane.setLayoutData(gd_timeSliderPane); return timeSliderPane; diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java index 9d6847c..d484730 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java @@ -40,7 +40,6 @@ public class RangeSlider extends Canvas { private int previousUpperValue, previousLowerValue; private int startDragUpperValue, startDragLowerValue; private Point startDragPoint; - private final boolean isSmooth; private final boolean isFullSelection=false; private final boolean isHighQuality; private final boolean isOn; @@ -68,7 +67,6 @@ public class RangeSlider extends Canvas { maximum = upperValue = 100; increment = 1; pageIncrement = 10; - isSmooth = (style & SWT.SMOOTH) == SWT.SMOOTH; isHighQuality = (style & SWT.HIGH) == SWT.HIGH; isOn = (style & SWT.ON) == SWT.ON; selectedElement = NONE; @@ -86,7 +84,7 @@ public class RangeSlider extends Canvas { @Override public int getStyle() { - return super.getStyle() | (isSmooth ? SWT.SMOOTH : SWT.NONE) | // + return super.getStyle() | // (isOn ? SWT.ON : SWT.NONE) | // (isFullSelection ? SWT.CONTROL : SWT.NONE) | // (isHighQuality ? SWT.HIGH : SWT.NONE); @@ -166,7 +164,8 @@ public class RangeSlider extends Canvas { } } - + private boolean busy = false; + private void handleMouseMove(final Event e) { if (selectedElement==NONE) { final boolean wasUpper = upperHover; @@ -190,28 +189,20 @@ public class RangeSlider extends Canvas { } upperValue = newUpper; lowerValue = newLower; - if (!isSmooth) { - lowerValue = (int) (Math.ceil(lowerValue / increment) * increment) - increment; - upperValue = (int) (Math.ceil(upperValue / increment) * increment) - increment; - } handleToolTip(lowerValue, upperValue); } else if (selectedElement == UPPER) { - upperValue = (int) Math.round((x - 9d) / computePixelSizeForSlider()) + minimum; - if (!isSmooth) { - upperValue = Math.min(lowerValue, (int) (Math.ceil(upperValue / increment) * increment) - increment); - } + upperValue = (int) Math.round((double)(x - markerWidth) / computePixelSizeForSlider()) + minimum; checkUpperValue(); handleToolTip(upperValue); } else if (selectedElement == LOWER){ - lowerValue = (int) Math.round((x - 9d) / computePixelSizeForSlider()) + minimum; - if (!isSmooth) { - lowerValue = Math.max(upperValue, (int) (Math.ceil(lowerValue / increment) * increment) - increment); - } + lowerValue = (int) Math.round((double)(x - markerWidth) / computePixelSizeForSlider()) + minimum; checkLowerValue(); handleToolTip(lowerValue); } - if (isOn) { + if (isOn && !busy) { validateNewValues(e); + busy=true; + getDisplay().timerExec(50, ()->{busy=false;}); } else { redraw(); } @@ -565,12 +556,6 @@ public class RangeSlider extends Canvas { return pageIncrement; } -// public void setIncrement(final int increment) { -// checkWidget(); -// this.increment = increment; -// redraw(); -// } - public void setMaximum(final int value) { setLimits(minimum, value); } @@ -616,12 +601,6 @@ public class RangeSlider extends Canvas { setValues(value, upperValue); } -// public void setPageIncrement(final int pageIncrement) { -// checkWidget(); -// this.pageIncrement = pageIncrement; -// redraw(); -// } - public void setValues(final int[] values) { if (values.length == 2) { setValues(values[0], values[1]); @@ -642,6 +621,9 @@ public class RangeSlider extends Canvas { e.type=SWT.Selection; e.doit=true; validateNewValues(e); + } else { + increment = Math.max(1, (upperValue-lowerValue)/100); + pageIncrement = Math.max(1, (upperValue-lowerValue)/2); } redraw(); } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomBar.java similarity index 96% rename from plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java rename to plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomBar.java index 3bac523..593a5a2 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/TimeZoomScrollbar.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/ZoomBar.java @@ -12,10 +12,10 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.wb.swt.SWTResourceManager; -public class TimeZoomScrollbar extends Composite { +public class ZoomBar extends Composite { static public interface IProvider { - TimeZoomScrollbar getScrollBar(); + ZoomBar getScrollBar(); } final RangeSlider timeSlider; @@ -26,7 +26,7 @@ public class TimeZoomScrollbar extends Composite { * @param parent * @param style */ - public TimeZoomScrollbar(Composite parent, int style) { + public ZoomBar(Composite parent, int style) { super(parent, SWT.NO_FOCUS); GridLayout gridLayout = new GridLayout(3, false); gridLayout.horizontalSpacing = 0; From 7dbcffe95db963f5de97ccca11d62106be388781 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 7 Jan 2022 21:25:01 +0100 Subject: [PATCH 8/8] fix layout for auto-hiding scrollbar (e.g. GTK) --- README.md | 62 ++++++++++++------- .../ui/swt/internal/WaveformView.java | 27 +++++++- .../ui/swt/internal/slider/RangeSlider.java | 6 +- 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 589cc20..e330fb0 100644 --- a/README.md +++ b/README.md @@ -30,25 +30,43 @@ Legend: * Mouse Scroll wheel: MScrl * Context any means Name List, Value List or Waveform -| Input | Modifier | Context | Action | -|-----------|----------|----------|-----------------------------------| -| LMB klick | | any | select | -| LMB klick | Shift | Waveform | move selected marker to position | -| LMB klick | Control | Waveform | move cursor to position | -| LMB drag | | Waveform | zoom to range | -| MMB klick | | Waveform | move selected marker to position | -| MScrl | | any | scroll window up/down | -| MScrl | Shift | any | scroll window left/right | -| Key left | | Waveform | scroll window to the left (slow) | -| Key right | | Waveform | scroll window to the right (slow) | -| Key left | Shift | Waveform | scroll window to the left (fast) | -| Key right | Shift | Waveform | scroll window to the right (fast) | -| Key up | | Waveform | move selection up | -| Key down | | Waveform | move selection down | -| Key up | Control | Waveform | move selected track up | -| Key down | Control | Waveform | move selected track down | -| Key + | Control | Waveform | zoom in | -| Key - | Control | Waveform | zoom out | -| Key Pos1 | | Waveform | jump to selected marker | -| Key End | | Waveform | jump to cursor | -| Key Del | | any | delete selected entries | +| Input | Modifier | Context | Action | +|------------|----------|----------|-----------------------------------| +| LMB click | | any | select | +| LMB click | Shift | Waveform | move selected marker to position | +| LMB click | Control | Waveform | move cursor to position | +| LMB drag | | Waveform | zoom to range | +| MMB click | | Waveform | move selected marker to position | +| MScrl | | any | scroll window up/down | +| MScrl | Shift | any | scroll window left/right | +| MScrl | Control | Waveform | zoom in/out | +| Key left | | Waveform | scroll window to the left (slow) | +| Key right | | Waveform | scroll window to the right (slow) | +| Key left | Shift | Waveform | scroll window to the left (fast) | +| Key right | Shift | Waveform | scroll window to the right (fast) | +| Key up | | Waveform | move selection up | +| Key down | | Waveform | move selection down | +| Key up | Control | Waveform | move selected track up | +| Key down | Control | Waveform | move selected track down | +| Key + | Control | Waveform | zoom in | +| Key - | Control | Waveform | zoom out | +| Key Pos1 | | Waveform | jump to selected marker | +| Key End | | Waveform | jump to cursor | +| Key Del | | any | delete selected entries | +| LMB click | | ZoomBar | increment/decrement 1 page | +| LMB drag | | ZoomBar | drag both markers (pan) | +| LMB drag | Control | ZoomBar | drag one marker (zoom) | +| MMB drag | | ZoomBar | drag one marker (zoom) | +| xMB dclick | | ZoomBar | pan to position | +| MScrl | | ZoomBar | scroll window left/right | +| MScrl | Shift | ZoomBar | scroll window left/right double speed | +| MScrl | Control | ZoomBar | zoom in/out | +| Key left | | ZoomBar | scroll window to the left (slow) | +| Key right | | ZoomBar | scroll window to the right (slow) | +| Key up | | ZoomBar | scroll window to the left (slow) | +| Key down | | ZoomBar | scroll window to the right (slow) | +| Key PgUp | | ZoomBar | scroll window to the left (fast) | +| Key PgDown | | ZoomBar | scroll window to the right (fast) | +| Key Pos1 | | ZoomBar | scroll to begin | +| Key End | | ZoomBar | scroll to end | + diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index ae2347a..c0c3fae 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -113,6 +113,10 @@ public class WaveformView implements IWaveformView { private final Canvas valueList; + private final Control nameFill; + + private final Control valueFill; + final WaveformCanvas waveformCanvas; final ToolTipHandler toolTipHandler; @@ -379,7 +383,10 @@ public class WaveformView implements IWaveformView { @Override public void controlResized(ControlEvent e) { nameListScrolled.getVerticalBar().setVisible(false); - + if(nameListScrolled.getSize().y == nameList.getSize().y) { + ((GridData)nameFill.getLayoutData()).heightHint=18; + namePane.layout(); + } } }); nameList = new Canvas(nameListScrolled, SWT.NONE) { @@ -398,7 +405,8 @@ public class WaveformView implements IWaveformView { }); nameList.addMouseListener(nameValueMouseListener); nameListScrolled.setContent(nameList); - + nameFill = createFill(namePane); + createTextPane(valuePane, "Value"); valuePane.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); @@ -411,7 +419,10 @@ public class WaveformView implements IWaveformView { @Override public void controlResized(ControlEvent e) { valueListScrolled.getVerticalBar().setVisible(false); - + if(valueListScrolled.getSize().y == valueList.getSize().y) { + ((GridData)valueFill.getLayoutData()).heightHint=18; + valuePane.layout(); + } } }); valueList = new Canvas(valueListScrolled, SWT.NONE) { @@ -430,6 +441,7 @@ public class WaveformView implements IWaveformView { }); valueList.addMouseListener(nameValueMouseListener); valueListScrolled.setContent(valueList); + valueFill = createFill(valuePane); waveformCanvas.setMaxTime(1); waveformCanvas.addPaintListener(waveformMouseListener); @@ -489,6 +501,15 @@ public class WaveformView implements IWaveformView { }); } + private Control createFill(Composite pane) { + Label cLabel = new Label(pane, SWT.NONE); + cLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); + GridData gd_cLabel = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); + gd_cLabel.heightHint = 0; + cLabel.setLayoutData(gd_cLabel); + return cLabel; + } + private void createTextPane(Composite namePane, String text) { GridLayout glNamePane = new GridLayout(1, false); glNamePane.verticalSpacing = 0; diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java index d484730..2f4964c 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/slider/RangeSlider.java @@ -92,11 +92,11 @@ public class RangeSlider extends Canvas { private void addMouseListeners() { addListener(SWT.MouseDown, e -> { - if (e.button == 1) { + if (e.button == 1 || e.button == 2) { selectKnobs(e); selectedElement = (lowerHover ? LOWER : NONE) | (upperHover ? UPPER : NONE); if (selectedElement!=NONE) { - if((e.stateMask & SWT.CTRL)==0) + if((e.stateMask & SWT.CTRL)==0 && e.button != 2) selectedElement=BOTH; startDragLowerValue = previousLowerValue = lowerValue; startDragUpperValue = previousUpperValue = upperValue; @@ -112,7 +112,7 @@ public class RangeSlider extends Canvas { super.setToolTipText(clientToolTipText); selectedElement=NONE; redraw(); - } else { + } else if (e.button == 1) { if(e.x