implement scrollbar adapter and first version of zooming scrollbar
Before Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 307 B |
@ -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();
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.minres.scviewer.database.ui.swt.internal;
|
||||
|
||||
public interface IWaveformScrollBarProvider {
|
||||
|
||||
IScrollBar getHorizontalSb();
|
||||
IScrollBar getVerticalSb();
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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<CursorPainter> cursorPainters;
|
||||
|
||||
IScrollBar horizontal;
|
||||
IScrollBar vertical;
|
||||
|
||||
HashMap<IWaveform, IWaveformPainter> 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)) {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
@ -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.x<sz.x-1;
|
||||
final boolean within_y = event.y>0 && event.y<sz.y-1;
|
||||
hover= within_x && within_y;
|
||||
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);
|
||||
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 <code>SelectionListener</code> interface.
|
||||
* <p>
|
||||
* <code>widgetSelected</code> is called when the user changes the receiver's
|
||||
* value. <code>widgetDefaultSelected</code> is not called.
|
||||
* </p>
|
||||
*
|
||||
* @param listener the listener which should be notified
|
||||
*
|
||||
* @exception IllegalArgumentException
|
||||
* <ul>
|
||||
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
||||
* </ul>
|
||||
* @exception SWTException
|
||||
* <ul>
|
||||
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
|
||||
* disposed</li>
|
||||
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
|
||||
* thread that created the receiver</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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
|
||||
* <ul>
|
||||
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
||||
* </ul>
|
||||
* @exception SWTException
|
||||
* <ul>
|
||||
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
|
||||
* disposed</li>
|
||||
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
|
||||
* thread that created the receiver</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 352 B |
After Width: | Height: | Size: 326 B |
After Width: | Height: | Size: 352 B |
After Width: | Height: | Size: 305 B |
After Width: | Height: | Size: 302 B |
After Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 307 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 343 B |
After Width: | Height: | Size: 385 B |