<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="widget_src"/>
<classpathentry kind="src" path="jaxb_src"/>
<classpathentry kind="src" path="resource"/>
<classpathentry exported="true" kind="lib" path="lib/swt.jar" sourcepath="lib/src.zip"/>
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+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.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+
+public class CheckBoxButton extends Canvas {
+ private Image image = null;
+ private Image imageHover = null;
+ private Image checkedImage = null;
+ private Image checkedImageHover = null;
+ private boolean isSelected = false;
+ private boolean isHover = false;
+
+ private Color checkedBackground = null;
+
+ public CheckBoxButton(Composite parent, int style) {
+ super(parent, SWT.DOUBLE_BUFFERED | style);
+
+ initButton();
+ addListeners();
+ }
+
+ protected void initButton() {
+ image = ImageResources.CHECKBOX_UNCHECKED_NML;
+ imageHover = ImageResources.CHECKBOX_UNCHECKED_HOVER;
+ checkedImage = ImageResources.CHECKBOX_CHECKED_NML;
+ checkedImageHover = ImageResources.CHECKBOX_CHECKED_HOVER;
+ }
+
+ private void addListeners() {
+ addPaintListener(paintListener);
+ addListener(SWT.MouseDown, mouseListener);
+ addListener(SWT.MouseUp, mouseListener);
+ addListener(SWT.MouseEnter, mouseListener);
+ addListener(SWT.MouseExit, mouseListener);
+ addDisposeListener(disposeListener);
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ checkWidget();
+ int width = 0, height = 0;
+
+ Rectangle bounds = image.getBounds();
+ width = bounds.width;
+ height = bounds.height;
+
+ if (wHint != SWT.DEFAULT)
+ width = wHint;
+
+ if (hHint != SWT.DEFAULT)
+ height = hHint;
+
+ return new Point(width, height);
+ }
+
+ private DisposeListener disposeListener = new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(DisposeEvent arg0) {
+ Helper.tryDispose(image, imageHover, checkedImage, checkedImageHover, checkedBackground);
+ }
+ };
+
+ private PaintListener paintListener = new PaintListener() {
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ Rectangle rect = ((Canvas) e.widget).getClientArea();
+
+ if (isSelected && checkedBackground != null) {
+ e.gc.setBackground(checkedBackground);
+ } else {
+ e.gc.setBackground(getBackground());
+ }
+ e.gc.fillRectangle(rect);
+
+ Image img = image;
+ if (isSelected) {
+ img = isHover ? checkedImageHover : checkedImage;
+ } else {
+ img = isHover ? imageHover : image;
+ }
+
+ Rectangle bounds = img.getBounds();
+ int x = rect.x + (rect.width - bounds.width) / 2;
+ int y = rect.y + (rect.height - bounds.height) / 2;
+
+ if (null != img) {
+ e.gc.drawImage(img, x, y);
+ }
+ }
+ };
+
+ public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ addListener(SWT.Selection, new TypedListener(listener));
+ addListener(SWT.DefaultSelection, new TypedListener(listener));
+ }
+
+ public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ removeListener(SWT.Selection, listener);
+ removeListener(SWT.DefaultSelection, listener);
+ }
+
+ protected Listener mouseListener = new Listener() {
+
+ @Override
+ public void handleEvent(Event event) {
+ if (!isEnabled()) {
+ return;
+ }
+
+ CheckBoxButton button = (CheckBoxButton) event.widget;
+ if (event.type == SWT.MouseDown) {
+ setSelection(!isSelection());
+ button.notifyListeners(SWT.Selection, new Event());
+ } else if (event.type == SWT.MouseEnter) {
+ isHover = true;
+ redraw();
+ } else if (event.type == SWT.MouseExit) {
+ isHover = false;
+ redraw();
+ }
+ }
+ };
+
+ public void setSelection(boolean selected) {
+ checkWidget();
+ isSelected = selected;
+ }
+
+ public boolean isSelection() {
+ checkWidget();
+ return isSelected;
+ }
+
+ public void setSelectedBackground(Color color) {
+ checkWidget();
+ if (color == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ this.checkedBackground = color;
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public final class ColorResources {
+ // Table Column
+ public static Color COLUMN_FONT_COLOR
+ = new Color(Display.getCurrent(), new RGB(41, 41, 41));
+ public static Color COLUMN_BG_COLOR
+ = new Color(Display.getCurrent(), new RGB(230, 231, 233));
+
+ // Table Item
+ public static Color ITEM_FONT_COLOR
+ = new Color(Display.getCurrent(), new RGB(96, 115, 124));
+ public static Color ITEM_SELECTED_FONT_COLOR
+ = new Color(Display.getCurrent(), new RGB(0, 0, 0));
+
+ public static Color ITEM_BG_COLOR_ODD
+ = new Color(Display.getCurrent(), new RGB(240, 241, 243));
+ public static Color ITEM_BG_COLOR_EVEN
+ = new Color(Display.getCurrent(), new RGB(255, 255, 255));
+ public static Color ITEM_HOVER_BG_COLOR
+ = new Color(Display.getCurrent(), new RGB(226, 246, 255));
+ public static Color ITEM_SELECTED_BG_COLOR
+ = new Color(Display.getCurrent(), new RGB(204, 239, 255));
+ public static Color ITEM_FOCUST_OUT_SELECTED_BG_COLOR
+ = new Color(Display.getCurrent(), new RGB(200, 200, 200));
+
+ public static Color COLUMN_CONTENTS_BG_COLOR
+ = new Color(Display.getCurrent(), new RGB(204, 239, 250)); // blue
+
+ public static Color DEFAULT_STROKE
+ = new Color(Display.getCurrent(), new RGB(194, 208, 211));
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Display;
+
+public class FontResources {
+ public static Font COLUMN_FONT = setSizeDefaultFont(12);
+ public static Font ITEM_FONT = setSizeDefaultFont(11);
+
+ private static boolean isMac = false;
+ private static boolean isWin = false;
+ private static boolean isLinux = false;
+ static {
+
+ if (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1) {
+ isLinux = true;
+ } else if (System.getProperty("os.name").toLowerCase().indexOf("win") > -1) {
+ isWin = true;
+ } else if (System.getProperty("os.name").toLowerCase().indexOf("mac") > -1) {
+ isMac = true;
+ }
+ }
+
+ private static Font defaultFont = null;
+
+ static {
+ defaultFont = getDADefaultFont();
+ }
+
+ public static Font getDADefaultFont() {
+ if (defaultFont == null) {
+ String fontName = null;
+ if (isLinux) {
+ fontName = "Dejavu Sans";
+ } else if (isWin) {
+ fontName = "Verdana";
+ } else if (isMac) {
+ fontName = "Lucida Grande";
+ } else {
+ defaultFont = Display.getCurrent().getSystemFont();
+ return defaultFont;
+ }
+ defaultFont = isMac
+ ? new Font(Display.getCurrent(), new FontData[] { new FontData(fontName, 11, SWT.NORMAL) })
+ : new Font(Display.getCurrent(), new FontData[] { new FontData(fontName, 9, SWT.NORMAL) });
+ }
+
+ return defaultFont;
+ }
+
+ public static Font setSizeDefaultFont(int size) {
+ if (defaultFont == null) {
+ defaultFont = getDADefaultFont();
+ }
+
+ if (isMac) {
+ size = size + 2;
+ }
+
+ FontData[] fontData = defaultFont.getFontData();
+ for (int i = 0; i < fontData.length; i++) {
+ fontData[i].setHeight(size);
+ }
+ return new Font(Display.getCurrent(), fontData);
+ }
+
+ public static Font setStyleDefaultFont(int style) {
+ if (defaultFont == null) {
+ defaultFont = getDADefaultFont();
+ }
+ FontData[] fontData = defaultFont.getFontData();
+ for (int i = 0; i < fontData.length; i++) {
+ fontData[i].setStyle(style);
+ }
+ return new Font(Display.getCurrent(), fontData);
+ }
+
+ public static Font setStyleAndSizeDefaultFont(int style, int size) {
+ if (defaultFont == null) {
+ defaultFont = getDADefaultFont();
+ }
+
+ if (isMac) {
+ size = size + 2;
+ }
+
+ FontData[] fontData = defaultFont.getFontData();
+ for (int i = 0; i < fontData.length; i++) {
+ fontData[i].setStyle(style);
+ fontData[i].setHeight(size);
+ }
+ return new Font(Display.getCurrent(), fontData);
+ }
+
+ public static Font setStyleFont(int style, Font font) {
+ FontData[] fontData = font.getFontData();
+ for (int i = 0; i < fontData.length; i++) {
+ fontData[i].setStyle(style);
+ }
+ return new Font(Display.getCurrent(), fontData);
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.widgets.Widget;
+
+public class Helper {
+
+ public static int checkBits( int style, int int0, int int1, int int2, int int3, int int4, int int5 ) {
+ int mask = int0 | int1 | int2 | int3 | int4 | int5;
+ int result = style;
+
+ if( (result & mask) == 0 ) {
+ result |= int0;
+ }
+
+ if((result & int0) != 0) {
+ result = (result & ~mask) | int0;
+ }
+ if((result & int1) != 0) {
+ result = (result & ~mask) | int1;
+ }
+ if((result & int2) != 0) {
+ result = (result & ~mask) | int2;
+ }
+ if((result & int3) != 0) {
+ result = (result & ~mask) | int3;
+ }
+ if((result & int4) != 0) {
+ result = (result & ~mask) | int4;
+ }
+ if( (result & int5) != 0) {
+ result = (result & ~mask) | int5;
+ }
+ return result;
+ }
+
+ public static void tryDispose(final Object... Disposables) {
+ if (null == Disposables) {
+ return;
+ }
+
+ for (Object obj : Disposables) {
+ if (null == obj) {
+ continue;
+ }
+ if (obj instanceof Widget) {
+ ((Widget) obj).dispose();
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+public class ImageResources {
+ public static Image CHECKBOX_UNCHECKED_HOVER = getImage("btn_checkbox_unchecked_hover", "png");
+ public static Image CHECKBOX_UNCHECKED_NML = getImage("btn_checkbox_unchecked_nml", "png");
+ public static Image CHECKBOX_CHECKED_HOVER = getImage("btn_checkbox_checked_hover", "png");
+ public static Image CHECKBOX_CHECKED_NML = getImage("btn_checkbox_checked_nml", "png");
+ public static Image SORT_INDICATOR_UP = getImage("up", "png");
+ public static Image SORT_INDICATOR_DOWN = getImage("down", "png");
+
+ public static Image getImage(String name, String extension) {
+ Image i = null;
+ ClassLoader loader = ImageResources.class.getClassLoader();
+ if (loader != null) {
+ InputStream is = loader.getResourceAsStream("table/" + name + "." + extension);
+ if (is != null) {
+ i = new Image(Display.getCurrent(), is);
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return i;
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+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.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+
+public class Table extends TableScrolledComposite {
+ private static final int[] EMPTY_SELECTION = new int[0];
+ private static final int DEFAULT_COLUMN_HEIGHT = 30;
+ private static final int DEFAULT_ITEM_HEIGHT = 30;
+ private static final int DEFAULT_SELECTED_ITEM_HEIGHT = 90;
+ private static final int CHECK_BOX_WIDTH = 30;
+
+ private TableItem[] items;
+ private int[] selection;
+ TableItem currentItem;
+ private int itemCount;
+ private int lastSelectedIndex = -1;
+ private int focusIndex;
+ private int topIndex = 0;
+
+ private int selectedItemHeight = DEFAULT_SELECTED_ITEM_HEIGHT;
+ private int itemHeight = DEFAULT_ITEM_HEIGHT;
+
+ private List<TableColumn> columns = new ArrayList<TableColumn>();
+ private int[] columnOrder;
+ private TableColumn sortColumn;
+ private int sortDirection;
+ private int columnHeight = DEFAULT_COLUMN_HEIGHT;
+
+ private boolean headerVisible = true;
+ private boolean linesVisible = true;
+
+ Composite table = null;
+ Composite tableItem = null;
+ Composite tableColumn = null;
+ private int width = 0;
+ private int tableWidth = 0;
+ private int tableHeight = 0;
+
+ private boolean isCtrlKeyOn;
+ private boolean isShiftKeyOn;
+
+ private boolean isCheck = false;
+ private int checkBoxWidth = CHECK_BOX_WIDTH;
+ private CheckBoxButton checkBox;
+
+ public Table(Composite parent, int style) {
+ super(parent, checkStyle(style));
+
+ table = new Composite(this, SWT.None);
+ this.setContent(table);
+
+ tableColumn = new Composite(table, SWT.None);
+
+ tableItem = new Composite(table, SWT.NONE);
+ tableItem.setBackground(ColorResources.ITEM_SELECTED_BG_COLOR);
+ this.setTableItemContent(tableItem);
+
+ focusIndex = -1;
+ sortDirection = SWT.None;
+ setTableEmpty();
+
+ if ((style & SWT.CHECK) != 0) {
+ isCheck = true;
+ checkBox = new CheckBoxButton(tableColumn, SWT.None);
+ checkBox.setBackground(ColorResources.COLUMN_BG_COLOR);
+ checkBox.setSelectedBackground(checkBox.getBackground());
+
+ }
+
+ addListener();
+ }
+
+ private void addListener() {
+ tableItem.addKeyListener(controlKeyEvent);
+ tableItem.addPaintListener(tableItemPaintListener);
+ tableColumn.addPaintListener(tableColumnPaintListener);
+
+ this.addControlListener(controlListener);
+ //this.addListener(SWT.FocusIn, foucusEventListener);
+ //this.addListener(SWT.FocusOut, foucusEventListener);
+
+ if (isCheck && checkBox != null) {
+ checkBox.addSelectionListener(new SelectionListener(){
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (checkBox.isSelection()) {
+ _selectAll(true);
+ } else {
+ _selectAll(false);
+ }
+ }
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+ }
+
+ public void addSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ }
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+ }
+
+ public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ }
+ removeListener (SWT.Selection, listener);
+ removeListener (SWT.DefaultSelection,listener);
+ }
+
+ private void setTableEmpty() {
+ items = new TableItem[4];
+ selection = EMPTY_SELECTION;
+ }
+
+ private static int checkStyle(int style) {
+ int result = style;
+
+ if( ( style & SWT.NO_SCROLL ) == 0 ) {
+ result |= SWT.H_SCROLL | SWT.V_SCROLL;
+ }
+
+ /* GTK is always FULL_SELECTION */
+ style |= SWT.FULL_SELECTION;
+ return Helper.checkBits(result, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+ }
+
+ public void clear(int index) {
+ checkWidget ();
+ if (!(0 <= index && index < itemCount)) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ TableItem item = items[index];
+ if (item != null) {
+ item.clear ();
+ }
+ }
+
+ public void clear(int start, int end){}
+ public void clear(int[] indices){}
+
+ public void clearAll () {
+ checkWidget ();
+ for (TableItem item : items) {
+ if (item != null) {
+ item.clear();
+ }
+ }
+ }
+
+ private void removeItem(int index) {
+ TableItem item = items[index];
+ if (item != null && !item.isDisposed()) {
+ item.dispose();
+ itemCount--;
+ } else {
+ destroyItem(null);
+ }
+ }
+
+ public void removeAll() {
+ checkWidget();
+ while (itemCount > 0) {
+ removeItem(0);
+ }
+ }
+
+ public void remove(int index) {
+ checkWidget();
+ if (!(0 <= index && index < itemCount)) {
+ SWT.error(SWT.ERROR_ITEM_NOT_REMOVED);
+ }
+ removeItem(index);
+ }
+
+ public void remove(int start, int end) {}
+ public void remove(int[] indices) {}
+
+ private void removeFromSelection(int index) {
+ if (index < 0 || index >= itemCount) {
+ return;
+ }
+
+ for (int i = 0; i < selection.length; i++) {
+ if (index == selection[i]) {
+ int length = selection.length;
+ int[] newSelection = new int[length - 1];
+ System.arraycopy(selection, 0, newSelection, 0, i);
+ if (i < length - 1) {
+ System.arraycopy(selection, i+1, newSelection, i, length - i - 1);
+ }
+ selection = newSelection;
+ break;
+ }
+ }
+ }
+
+ public void deselect(int index) {
+ checkWidget();
+ boolean isNeedReset = selection.length == 1;
+ removeFromSelection(index);
+ if (isNeedReset) {
+ lastSelectedIndex = -1;
+ this.rearrange(index);
+ }
+ }
+
+ public void deselect(int start, int end) {
+ checkWidget();
+ if (start == 0 && end == itemCount - 1) {
+ deselectAll();
+ } else {
+ int actualStart = Math.max(0, start);
+ for (int i = actualStart; i <= end; i++) {
+ removeFromSelection(i);
+ }
+ }
+ }
+
+ public void deselect(int[] indices) {}
+
+ public void deselectAll() {
+ checkWidget();
+ selection = EMPTY_SELECTION;
+ }
+
+ public void select(int index) {
+ checkWidget();
+ if (index >= 0 && index < itemCount) {
+ if ((getStyle() & SWT.SINGLE) != 0) {
+ selection = new int[] {index};
+ } else {
+ if (!isSelected(index)) {
+ int length = selection.length;
+ int[] newSelection = new int[length + 1];
+ System.arraycopy(selection, 0, newSelection, 0, length);
+ newSelection[length] = index;
+ selection = newSelection;
+ }
+ }
+ }
+ }
+
+ public void select(int start, int end) {
+ checkWidget();
+ if (end < 0 || start > end) {
+ return;
+ }
+
+ if ((getStyle() & SWT.SINGLE) != 0 && start != end) {
+ return;
+ }
+
+ if (itemCount == 0 || start >= itemCount) {
+ return;
+ }
+
+ int adjustedStart = Math.max(0, start);
+ int adjustedEnd = Math.min(end, itemCount - 1);
+ if (adjustedStart == 0 && adjustedEnd == itemCount - 1) {
+ selectAll();
+ } else {
+ for (int i = adjustedStart; i <= adjustedEnd; i++) {
+ select(i);
+ }
+ }
+ }
+
+ public void select(int[] indices) {
+ checkWidget();
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ int length = indices.length;
+ if (length != 0 && ((getStyle() & SWT.SINGLE) == 0
+ || length <= 1)) {
+// for (int i = length - 1; i >= 0; --i) {
+// select(indices[i]);
+// }
+ for (int i = 0; i < length; i++) {
+ select(indices[i]);
+ }
+ }
+ }
+
+ public void selectAll() {
+ checkWidget();
+ if ((getStyle() & SWT.SINGLE) == 0) {
+ for (int i = items.length; i > 0; i--) {
+ select(i-1);
+ }
+ }
+ }
+
+ public boolean isSelected(int index) {
+ checkWidget();
+ boolean result = false;
+ if (index >= 0 && index < itemCount) {
+ if (selection != null) {
+ for (int i = 0; i < selection.length; i++) {
+ if (selection[i] == index) {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the zero-relative index of the item which is currently selected,
+ * or -1 if no item is selected.
+ * @return the index of the selected item
+ */
+ public int getSelectionIndex() {
+ checkWidget();
+ int result = -1;
+ int topSelectedIndex = -1;
+ for (int i = 0; i < selection.length; i++) {
+ if (focusIndex == selection[i]) {
+ result = selection[i];
+ }
+ if (topSelectedIndex == -1) {
+ topSelectedIndex = selection[i];
+ } else {
+ topSelectedIndex = Math.min(topSelectedIndex, selection[i]);
+ }
+ }
+ if (result == -1) {
+ result = topSelectedIndex;
+ }
+ return result;
+ }
+
+ public int getSelectionCount() {
+ checkWidget();
+ return selection.length;
+ }
+
+ public TableItem[] getSelection() {
+ checkWidget();
+ TableItem[] result = new TableItem[selection.length];
+ for (int i = 0; i < selection.length; i++) {
+ result[i] = _getItem(selection[i]);
+ }
+ return result;
+ }
+
+ private void rearrange(int index) {
+ if (lastSelectedIndex == -1) {
+ updateScrollBars(true);
+ items[index].updateSizeAndLocation(-1);
+ for (int i = index + 1; i < items.length; i ++) {
+ if (items[i] != null) {
+ items[i].updateLocation(-1);
+ }
+ }
+ } else {
+ if (lastSelectedIndex > index) {
+ items[index].updateSizeAndLocation(-1);
+ items[lastSelectedIndex].updateSizeAndLocation(-1);
+ for (int i = index + 1; i < lastSelectedIndex; i ++) {
+ if (items[i] != null) {
+ items[i].updateLocation(-1);
+ }
+ }
+ } else {
+ items[lastSelectedIndex].updateSizeAndLocation(-1);
+ items[index].updateSizeAndLocation(-1);
+ for (int i = lastSelectedIndex + 1; i < index; i ++) {
+ if (items[i] != null) {
+ items[i].updateLocation(-1);
+ }
+ }
+ }
+ }
+ lastSelectedIndex = index;
+ }
+
+ private void rearrange() {
+ if (lastSelectedIndex > -1) {
+ updateScrollBars(true);
+ items[lastSelectedIndex].updateSizeAndLocation(-1);
+ for (int i = lastSelectedIndex + 1; i < items.length; i++) {
+ if (items[i] != null) {
+ items[i].updateLocation(-1);
+ }
+ }
+ }
+ lastSelectedIndex = -1;
+ }
+
+ public void setSelection(int index) {
+ checkWidget();
+ deselectAll();
+ select(index);
+ if (index < itemCount) {
+ setFocusIndex(index);
+ }
+ rearrange(index);
+ showSelection();
+ }
+
+ public void setSelection(int start, int end) {
+ checkWidget();
+ deselectAll();
+ select(start, end);
+ if (end >= 0 && start <= end
+ && ((getStyle() & SWT.SINGLE) == 0 || start == end)
+ && itemCount != 0
+ && start < itemCount) {
+ setFocusIndex(Math.max(0, start));
+ }
+ if (selection.length == 1) {
+ rearrange(selection[0]);
+ } else if (selection.length >= 2 && lastSelectedIndex > -1) {
+ rearrange();
+ }
+ showSelection();
+ }
+
+ public void setSelection(TableItem item) {
+ checkWidget();
+ if (item == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ int index = indexOf(item);
+ if (index < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ checkWidget();
+ deselectAll();
+ select(index);
+ setFocusIndex(index);
+ rearrange(selection[index]);
+ showSelection();
+ }
+
+ public void setSelection(int[] indices ) {
+ checkWidget();
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ deselectAll();
+ select(indices);
+ int length = indices.length;
+ if (length != 0 && ((getStyle() & SWT.SINGLE) == 0
+ || length <= 1)) {
+ setFocusIndex(indices[0]);
+ }
+ if (selection.length == 1) {
+ rearrange(selection[0]);
+ } else if (selection.length >= 2 && lastSelectedIndex > -1) {
+ rearrange();
+ }
+ showSelection();
+ }
+
+ public void setSelection(TableItem[] items) {}
+
+ private void setFocusIndex(int focusIndex) {
+ if (focusIndex >= 0) {
+ this.focusIndex = focusIndex;
+ }
+ }
+
+ void _selectAll(boolean select) {
+ if (select) {
+ deselectAll();
+ selectAll();
+ rearrange();
+ } else {
+ deselectAll();
+ }
+
+ showSelection();
+ checkBox.redraw();
+ if (items.length > 0) {
+ Event e = new Event();
+ e.item = items[0];
+ e.widget = this;
+ notifyListeners(SWT.Selection, e);
+ }
+ }
+
+ // for table item
+ void _select(int index) {
+ if (selection.length == 1) {
+ lastSelectedIndex = selection[0];
+ }
+
+ if (isCheck && checkBox.isSelection()) {
+ checkBox.setSelection(false);
+ checkBox.redraw();
+ }
+
+ if ((getStyle() & SWT.SINGLE) != 0
+ || (!isCtrlKeyOn && !isShiftKeyOn)) {
+ setSelection(index);
+ } else if (isCtrlKeyOn) {
+ if (this.isSelected(index)) {
+ if (selection.length == 1) {
+ this.deselect(index);
+ int[] newSelection = new int[selection.length];
+ System.arraycopy(selection, 0, newSelection, 0, selection.length);
+ setSelection(newSelection);
+ } else {
+ this.deselect(index);
+ int[] newSelection = new int[selection.length];
+ System.arraycopy(selection, 0, newSelection, 0, selection.length);
+ setSelection(newSelection);
+ }
+ } else {
+ int length = selection != null ? selection.length : 0;
+ if (length == 0) {
+ setSelection(index);
+ } else {
+ int[] newSelection = new int[length + 1];
+ System.arraycopy(selection, 0, newSelection, 0, length);
+ newSelection[length] = index;
+ setSelection(newSelection);
+ }
+ }
+ } else if (isShiftKeyOn) {
+ if (selection.length > 0) {
+ if (index > (selection[selection.length - 1])) {
+ setSelection(selection[selection.length - 1], index);
+ } else {
+ setSelection(index, selection[selection.length - 1]);
+ }
+ } else {
+ setSelection(index);
+ }
+ }
+ Event e = new Event();
+ e.item = items[index];
+ e.widget = this;
+ notifyListeners(SWT.Selection, e);
+ }
+
+ public int getItemCount() {
+ checkWidget();
+ return itemCount;
+ }
+
+ public TableItem[] getItems() {
+ checkWidget();
+ TableItem[] result = new TableItem[itemCount];
+ if ((getStyle() & SWT.VIRTUAL) != 0) {
+ for (int i = 0; i < itemCount; i++) {
+ result[i] = _getItem(i);
+ }
+ } else {
+ System.arraycopy(items, 0, result, 0, itemCount);
+ }
+ return result;
+ }
+
+ public TableItem getItem(int index) {
+ checkWidget();
+ if (index < 0 || index >= itemCount) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return items[index];
+ }
+
+ public int indexOf(TableItem item) {
+ checkWidget();
+ if (item == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ for (int i = 0; i < itemCount; i++) {
+ if (items[i] == item) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private TableItem _getItem(int index) {
+ if ((getStyle() & SWT.VIRTUAL) != 0 && items[index] == null) {
+ items[index] = new TableItem(this, SWT.NONE, index);
+ }
+ return items[index];
+ }
+
+ public int getColumnCount() {
+ checkWidget();
+ return columns.size();
+ }
+
+ public TableColumn[] getColumns() {
+ checkWidget();
+ return (TableColumn[])columns.toArray();
+ }
+
+ public List<TableColumn> getColumnList() {
+ checkWidget();
+ return columns;
+ }
+
+ public TableColumn getColumn(int index) {
+ checkWidget();
+ return columns.get(index);
+ }
+
+ public int indexOf(TableColumn tableColumn) {
+ checkWidget();
+ if (tableColumn == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ return columns.indexOf(tableColumn);
+ }
+
+ public int[] getColumnOrder() {
+ checkWidget();
+ int[] result;
+ if (columns.size() == 0) {
+ result = new int[0];
+ } else {
+ result = new int[columns.size()];
+ System.arraycopy(columnOrder, 0, result, 0, columns.size());
+ }
+ return result;
+ }
+
+ public void setColumnOrder(int[] order) {
+ checkWidget();
+ if (order == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ int columnCount = columns.size();
+ if (order.length != columnCount) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if( columnCount > 0 ) {
+ int[] oldOrder = new int[ columnCount ];
+ System.arraycopy( columnOrder, 0, oldOrder, 0, columnOrder.length );
+ boolean reorder = false;
+ boolean[] seen = new boolean[ columnCount ];
+ for( int i = 0; i < order.length; i++ ) {
+ int index = order[ i ];
+ if( index < 0 || index >= columnCount ) {
+ SWT.error( SWT.ERROR_INVALID_RANGE );
+ }
+ if( seen[ index ] ) {
+ SWT.error( SWT.ERROR_INVALID_ARGUMENT );
+ }
+ seen[ index ] = true;
+ if( index != oldOrder[ i ] ) {
+ reorder = true;
+ }
+ }
+ if( reorder ) {
+ System.arraycopy( order, 0, columnOrder, 0, columnOrder.length );
+ FormData data = null;
+ TableColumn c = null;
+ for( int i = 0; i < seen.length; i++ ) {
+ c = columns.get(columnOrder[ i ]);
+ data = new FormData();
+ if (i == 0) {
+ data.top = new FormAttachment(0,0);
+ data.left = new FormAttachment(0, 0);
+ } else {
+ data.top = new FormAttachment(0,0);
+ data.left = new FormAttachment(columns.get(columnOrder[ i-1 ]));
+ }
+ data.width = c.getWidth();
+ data.height = 30;
+ c.setLayoutData(data);
+ c.redraw();
+ }
+
+ this.layout(true, true);
+ }
+ }
+ }
+
+ void createColumn(TableColumn column, final int index) {
+ if (index < 0) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ columns.add(index, column);
+
+ if (columnOrder == null) {
+ columnOrder = new int[] {index};
+ } else {
+ int length = columnOrder.length;
+ for (int i = index; i < length; i++) {
+ columnOrder[i]++;
+ }
+ int[] newColumnOrder = new int[ length + 1 ];
+ System.arraycopy( columnOrder, 0, newColumnOrder, 0, index );
+ System.arraycopy( columnOrder, index, newColumnOrder, index + 1, length - index );
+ columnOrder = newColumnOrder;
+ columnOrder[ index ] = index;
+ }
+
+ for (int i = 0; i < itemCount; i++) {
+ if (items[i] != null) {
+ items[i].shiftData(index);
+ }
+ }
+
+ updateScrollBars(true);
+ }
+
+ public void destroyColumn(TableColumn column) {
+ int index = columns.indexOf(column);
+ for (TableItem item : items) {
+ if (item != null) {
+ item.removeData(index);
+ }
+ }
+
+ // TODO
+ if (column == sortColumn) {
+ sortColumn = null;
+ }
+
+ columns.remove(column);
+
+ // remove from column order
+ int length = columnOrder.length;
+ int[] newColumnOrder = new int[length - 1];
+ int count = 0;
+ for (int i = 0; i < length; i++) {
+ if (columnOrder[i] == index) {
+ continue;
+ }
+
+ int newIndex = columnOrder[i];
+ if (index < newIndex) {
+ newIndex--;
+ }
+ newColumnOrder[count++] = newIndex;
+ }
+
+ updateScrollBars(true);
+ }
+
+ void createItem(TableItem item, int index) {
+ if (index < 0 || index > itemCount) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ if (itemCount == items.length) {
+ int length = items.length + 4;
+ TableItem[] newItems = new TableItem[length];
+ System.arraycopy(items, 0, newItems, 0, items.length);
+ items = newItems;
+ }
+
+ // Insert
+ System.arraycopy(items, index, items, index + 1, itemCount - index);
+ items[index] = item;
+ itemCount++;
+
+ adjustItemIndices( index );
+ // adjust the selection indices
+ /*
+ for( int i = 0; i < selection.length; i++ ) {
+ if( selection[ i ] >= index ) {
+ selection[ i ] = selection[ i ] + 1;
+ }
+ }
+ */
+ // advance focusIndex when an item is inserted before the focused item
+ if( index <= focusIndex ) {
+ focusIndex++;
+ }
+ updateScrollBars(true);
+ }
+
+ final void destroyItem(TableItem item) {
+ // TODO
+ }
+
+ private void adjustItemIndices(int start) {
+ for (int i = start; i < itemCount; i++) {
+ if (items[i] != null) {
+ items[i].setIndex(i);
+ }
+ }
+ }
+
+ static final int DEFAULT_WIDTH = 64;
+ static final int DEFAULT_HEIGHT = 64;
+ @Override
+ public Point computeSize( int wHint, int hHint, boolean changed ) {
+ checkWidget();
+ if (wHint != SWT.DEFAULT && wHint < 0) {
+ wHint = 0;
+ }
+ if (hHint != SWT.DEFAULT && hHint < 0) {
+ hHint = 0;
+ }
+
+ int width = 0;
+ int height = 0;
+ if( columns.size() > 0 ) {
+ for (TableColumn colum : columns) {
+ width += colum.getWidth();
+ }
+ } else {
+ //width = getItemsPreferredWidth( 0 );
+ }
+ height += getHeaderHeight();
+ //TODO: item height is fixed
+ height += getItemCount() * getItemHeight();
+ if( width == 0) {
+ width = DEFAULT_WIDTH;
+ }
+ if(height == 0) {
+ height = DEFAULT_HEIGHT;
+ }
+ if(wHint > 0) {
+ width = wHint;
+ }
+ if(hHint > 0) {
+ height = hHint;
+ }
+ int border = getBorderWidth();
+ width += border * 2;
+ height += border * 2;
+ /*
+ if( ( style & SWT.V_SCROLL ) != 0 ) {
+ width += getVerticalBar().getSize().x;
+ }
+ if( ( style & SWT.H_SCROLL ) != 0 ) {
+ height += getHorizontalBar().getSize().y;
+ }
+ */
+ return new Point( width, height );
+ }
+
+ private int getHeaderHeight() {
+ checkWidget();
+ int result = 0;
+ if(headerVisible) {
+ Font headerFont = FontResources.COLUMN_FONT; // TODO
+ int textHeight = (int)TextSizeUtil.getCharHeight(headerFont);
+ int imageHeight = 0;
+ for(int i = 0; i < columns.size(); i++) {
+ TableColumn column = columns.get(i);
+ /*
+ if(column.getText().contains("\n")) {
+ int columnTextHeight = TextSizeUtil.textExtent( headerFont, column.getText(), 0 ).y;
+ textHeight = Math.max( textHeight, columnTextHeight );
+ }
+ */
+ Image image = column.getImage();
+ int height = image == null ? 0 : image.getBounds().height;
+ if(height > imageHeight) {
+ imageHeight = height;
+ }
+ }
+ result = Math.max(textHeight, imageHeight);
+ result = Math.max(result, columnHeight);
+ }
+ return result;
+ }
+
+ public boolean getHeaderVisible() {
+ checkWidget();
+ return headerVisible;
+ }
+
+ public void setHeaderVisible(boolean headerVisible) {
+ checkWidget();
+ boolean changed = headerVisible != this.headerVisible;
+ this.headerVisible = headerVisible;
+ if (changed) {
+ updateScrollBars(true);
+ }
+ }
+
+ public boolean getLinesVisible() {
+ checkWidget();
+ return linesVisible;
+ }
+
+ public void setLinesVisible(boolean linesVisible) {
+ checkWidget();
+ this.linesVisible = linesVisible;
+ }
+
+ public TableColumn getSortColumn() {
+ checkWidget();
+ return sortColumn;
+ }
+
+ public void setSortColumn(TableColumn column) {
+ checkWidget();
+ if (column != null && column.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ sortColumn = column;
+ }
+
+ public int getSortDirection() {
+ checkWidget();
+ return sortDirection;
+ }
+
+ public void setSortDirection(int direction) {
+ checkWidget();
+ if ((direction & (SWT.UP | SWT.DOWN)) != 0
+ || direction == SWT.NONE) {
+ sortDirection = direction;
+ }
+ }
+
+ boolean vVisible = false;
+ boolean hVisible = false;
+ public void updateScrollBars(boolean isComputeSize) {
+ if (isComputeSize) {
+ computeTableSize();
+ }
+
+ Rectangle tableRect = new Rectangle(0, 0, tableWidth, tableHeight);
+ Rectangle tableItemRect = new Rectangle(0, 0, tableWidth, tableHeight - columnHeight);
+ hVisible = this.needHScroll(tableRect, false);
+ vVisible = this.needVScroll(tableItemRect, hVisible);
+ if (vVisible) {
+ hVisible = this.needHScroll(tableRect, vVisible);
+ }
+
+ setTableSize();
+ }
+
+ void computeTableSize() {
+ int width = 0;
+ for (TableColumn column : columns) {
+ width += column.getWidth();
+ }
+
+ tableWidth = width;
+ if (isCheck) {
+ tableWidth += CHECK_BOX_WIDTH;
+ }
+
+ if (getSelectionCount() == 1) {
+ tableHeight = columnHeight + (itemCount-1) * this.getItemHeight()
+ + this.getSelectedItemHeight();
+ } else {
+ tableHeight = columnHeight + itemCount * this.getItemHeight();
+ }
+ }
+
+ void setTableSize() {
+ Rectangle rect = this.getBounds();
+ if (vVisible) {
+ tableWidth += this.getScrollBarWidth();
+ }
+ if (hVisible) {
+ tableHeight += this.getScrollBarWidth();
+ }
+ int width = Math.max(tableWidth, rect.width);
+ int height = Math.max(tableHeight, rect.height);
+
+
+
+ table.setSize(width, height);
+ tableColumn.setBounds(0, 0, width, 30);
+ tableItem.setBounds(0, columnHeight, width, height - columnHeight);
+ }
+
+ public int getColumnHeightSize() {
+ return columnHeight;
+ }
+
+ public void setColumnHeightSize(int columnHeightSize) {
+ this.columnHeight = columnHeightSize;
+ }
+
+ public boolean checkData(TableItem tableItem, Object indexOf) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ private int leftOffset = 5;
+ int getLeftOffset() {
+ return this.leftOffset;
+ }
+
+ int getColumnLeftOffset(int index) {
+ int result = leftOffset;
+ if (index >= 0) {
+ result = isFixedColumn(index) ? 0 : leftOffset;
+ }
+ return result;
+ }
+
+ // TODO
+ private boolean isFixedColumn(int index) {
+ return false;
+ }
+
+ public void setTopIndex(int index) {
+ checkWidget();
+ if (this.topIndex != index
+ && index >= 0 && index < itemCount) {
+ adjustTopIndex();
+ if ((getStyle() & SWT.VIRTUAL) != 0) {
+ redraw();
+ }
+ }
+ }
+ public int getTopIndex() {
+ checkWidget();
+ return topIndex;
+ }
+
+ private void adjustTopIndex() {
+// int visibleItemCount = getVisibleItemCount(false);
+ int visibleItemCount = 0;
+ int correction = visibleItemCount == 0 ? 1 : 0;
+ if (topIndex > itemCount - visibleItemCount - correction) {
+ topIndex = Math.max(0, itemCount - visibleItemCount - correction);
+ }
+ }
+
+ public Rectangle getCellPadding() {
+ // TODO Auto-generated method stub
+ return new Rectangle(6, 3, 6, 3);
+ }
+
+ // SWT.CHECK
+ boolean isChecked() {
+ return isCheck;
+ }
+
+ int getCheckBoxWidth() {
+ return checkBoxWidth;
+ }
+/*
+ public Point getCheckSize() {
+ return new Point(0, 0);
+ }
+
+ public Point getCheckSize(int index) {
+ if (index == 0 && getColumnCount() == 0) {
+ return getCheckSize();
+ } else {
+ int[] columnOrder = getColumnOrder();
+ if(columnOrder[0] == index) {
+ return getCheckSize();
+ }
+ }
+ return new Point(0, 0);
+ }
+*/
+ public boolean hasColumnImages(int index) {
+ return columns.get(index).getImage() == null ? false : true;
+ }
+
+ public int getCellSpacing() {
+ // TODO Auto-generated method stub
+ return 5;
+ }
+
+ public int getItemHeight() {
+ checkWidget();
+ /*
+ int result = -1; //customItemHeight;
+ if (result == -1) {
+ int textHeight = (int)TextSizeUtil.getCharHeight(getFont());
+ int imageHeight = getItemImageSize().y;
+ result = Math.max(imageHeight, textHeight) + getCellPadding().height;
+ result = Math.max(itemHeight, result);
+ // TODO check style
+ }
+ return result;
+ */
+ return itemHeight;
+ }
+
+ public int getSelectedItemHeight() {
+ checkWidget();
+ return selectedItemHeight;
+ }
+
+ public void setItemHeight(int height) {
+ checkWidget();
+ if (height != itemHeight && height > 0) {
+ itemHeight = height;
+ }
+ }
+
+ public void setSelectedItemHeight(int height) {
+ checkWidget();
+ if (height != selectedItemHeight && height > 0) {
+ selectedItemHeight = height;
+ }
+ }
+
+ int getItemsPreferredWidth(int i) {
+ int width = 0;
+ for (TableItem item : items) {
+ if (item != null) {
+ int packWidth = item.getPackWidth(i);
+ if (packWidth > width) {
+ width = packWidth;
+ }
+ }
+ }
+ return width;
+ }
+
+ int getWidth() {
+ return width;
+ }
+
+ public void showColumn(TableColumn column) {}
+ public void showItem(TableItem item) {}
+ public void showSelection() {
+ for (TableItem item : items) {
+// if (item != null) {
+// Event event = new Event();
+// event.index = -1;
+// item.notifyListeners(SWT.Resize, event);
+// }
+ if (item != null) {
+ item.redraw();
+ }
+ }
+ }
+
+ protected ControlListener controlListener = new ControlListener() {
+ @Override
+ public void controlMoved(ControlEvent e) {
+ }
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ updateScrollBars(false);
+
+ for (TableItem item : items) {
+ if (item != null) {
+ item.updateSizeAndLocation(-1);
+ }
+ }
+ }
+ };
+
+ private PaintListener tableColumnPaintListener = new PaintListener() {
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ Rectangle rect= ((Composite)e.widget).getClientArea();
+ width = rect.width;
+
+ GC gc = e.gc;
+ if (headerVisible) {
+ gc.setBackground(ColorResources.COLUMN_BG_COLOR);
+ Rectangle columnRect = new Rectangle(0, 0, rect.width, columnHeight);
+ gc.setClipping(columnRect);
+ gc.fillRectangle(columnRect);
+ if (isCheck) {
+ checkBox.setBounds(0, 0, checkBoxWidth - 1, columnHeight);
+ gc.setForeground(ColorResources.DEFAULT_STROKE);
+ gc.drawLine(checkBoxWidth - 1, 0, checkBoxWidth -1, rect.height);
+ }
+ }
+ }
+ };
+
+ private PaintListener tableItemPaintListener = new PaintListener() {
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ Rectangle rect= ((Composite)e.widget).getClientArea();
+ width = rect.width;
+
+ GC gc = e.gc;
+ int top = 0;
+ int height = getItemHeight();
+ for (int i = 0; top < rect.height; i++, top += height) {
+ Rectangle drawingRect = new Rectangle(0, top, rect.width, height);
+ gc.setClipping(drawingRect);
+ if ((i%2) == 0) {
+ gc.setBackground(ColorResources.ITEM_BG_COLOR_EVEN);
+ } else {
+ gc.setBackground(ColorResources.ITEM_BG_COLOR_ODD);
+ }
+ gc.fillRectangle(drawingRect);
+ }
+
+ gc.setForeground(ColorResources.DEFAULT_STROKE);
+ gc.setLineWidth(1);
+ int leftOffset = isCheck ? checkBoxWidth : 0;
+ gc.setClipping(rect);
+ if (isCheck) {
+ gc.drawLine(checkBoxWidth -1, 0, checkBoxWidth - 1, rect.height);
+ }
+ for (TableColumn column : columns) {
+ int width = column.getWidth();
+
+ gc.drawLine(leftOffset + width-1, 0, leftOffset + width -1, rect.height);
+ leftOffset += width;
+ }
+ }
+
+ };
+
+ private KeyAdapter controlKeyEvent = new KeyAdapter() {
+ @ Override
+ public void keyPressed(KeyEvent e) {
+ switch (e.keyCode) {
+ case SWT.CTRL:
+ isCtrlKeyOn = true;
+ break;
+ case SWT.SHIFT:
+ if (!isCtrlKeyOn) {
+ isShiftKeyOn = true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ @ Override
+ public void keyReleased(KeyEvent e) {
+ switch (e.keyCode) {
+ case SWT.CTRL:
+ isCtrlKeyOn = false;
+ break;
+ case SWT.SHIFT:
+ isShiftKeyOn = false;
+ break;
+ case SWT.ARROW_UP:
+ if (lastSelectedIndex > 0) {
+ _select(lastSelectedIndex - 1);
+ }
+ break;
+ case SWT.ARROW_DOWN:
+ if (lastSelectedIndex > -1 && lastSelectedIndex < (itemCount-1)) {
+ _select(lastSelectedIndex + 1);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ protected Listener foucusEventListener = new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.FocusIn:
+ showSelection();
+ break;
+ case SWT.FocusOut:
+ showSelection();
+ break;
+ }
+ }
+ };
+
+ private Listener sortListener = new Listener() {
+
+ @Override
+ public void handleEvent(Event event) {
+ TableColumn column = (TableColumn)event.widget;
+ int index = columns.indexOf(column);
+ if (index == -1) {
+ return;
+ }
+
+ int dir = getSortDirection();
+
+ if (getSortColumn() != column) {
+ setSortColumn(column);
+ dir = SWT.UP;
+ }
+
+ TableItem[] newItems = new TableItem[itemCount];
+ int[] newSelection = new int[selection.length];
+ newItems[0] = items[0];
+ for (int i = 1; i < items.length; i++) {
+ if (items[i] == null) {
+ continue;
+ }
+ String value1 = items[i].getText(index);
+ if (value1 == null) {
+ continue;
+ }
+ int j = i - 1;
+
+ while (j >= 0) {
+ String value2 = newItems[j].getText(index);
+ int compare = value1.compareTo(value2);
+ if (compare < 0 && dir == SWT.UP) {
+ newItems[j + 1] = newItems[j];
+ j--;
+ } else if (compare > 0 && dir == SWT.DOWN){
+ newItems[j + 1] = newItems[j];
+ j--;
+ } else {
+ break;
+ }
+ }
+ newItems[j + 1] = items[i];
+// for (int j = 0; j < i; j++) {
+// if (items[j] == null) {
+// continue;
+// }
+// String value2 = items[j].getText(index);
+// boolean needSort = false;
+// int compare = collator.compare(value1, value2);
+// if (compare > 0 && dir == SWT.UP) {
+// needSort = true;
+// } else if (compare < 0 && dir == SWT.DOWN){
+// needSort = true;
+// }
+
+// if (needSort) {
+// TableItem item = items[i];
+// TableItem[] newItems = new TableItem[itemCount];
+// if (j > 0) {
+// System.arraycopy(items, 0, newItems, 0, j);
+// }
+// System.arraycopy(items, j, newItems,j+1, i - j);
+// System.arraycopy(items, i + 1, newItems, i + 1, itemCount - i - 1);
+// newItems[j] = item;
+// items = newItems;
+// adjustItemIndices(0);
+// }
+ }
+ adjustItemIndices(0);
+
+ for (int in = 0; in < selection.length; in++) {
+ TableItem item = items[selection[in]];
+ for (int i = 0; i < newItems.length; i++) {
+ if (newItems[i] == item) {
+ newSelection[in] = i;
+ break;
+ }
+ }
+ }
+ items = newItems;
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ setSortDirection(dir);
+ setSelection(newSelection);
+ showSelection();
+ }
+ };
+
+ public Listener getDifaultSortListener() {
+ checkWidget();
+ return sortListener;
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import java.util.ArrayList;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+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.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+
+public class TableColumn extends Canvas {
+ private static final int SORT_INDICATOR_WIDTH = 10;
+ private static final int SPACING = 5;
+ // minimum size
+ private static final int RESIZABLE_WIDTH = 10;
+ private static final int MIN_WIDTH = 20;
+ private static final int HEADERPADDING_WIDTH = 30;
+
+ private final Table parent;
+ private int style = 0;
+
+ private int width;
+ private String text;
+ private Image image;
+
+ private boolean resizable = false;
+ private boolean moveable = false;
+
+ // mouse hover and push
+ //private boolean isSelected = false;
+ private boolean isHoverState;
+ private Font font;
+ private Font selectedFont;
+ private Color background;
+ private Color selectedBackground;
+ private Color foreground;
+ private Color selectedForeground;
+
+ // resize
+ private boolean isResizedState;
+ private boolean isResizeableState;
+ private boolean setCursor;
+ private Cursor backupCursor;
+
+ // drag and drop
+ private TableColumnDragAndDrop dnd;
+ private boolean backupMoveable;
+ private Image dndImage;
+
+ // draw text
+ private String drawingText;
+ private boolean needRedrawingText = true;
+
+ //private SortButton sortButton;;
+ private Image sortIndicator;
+
+ public TableColumn(Table parent, int style) {
+ this(parent, style, checkNull(parent).getColumnCount());
+ }
+
+ public TableColumn(Table parent, int style, int index) {
+ super(parent.tableColumn, checkStyle(style));
+ this.parent = parent;
+ this.style = checkStyle(style);
+
+ this.resizable = true;
+
+ createColumn(index);
+ }
+
+ private static int checkStyle (int style) {
+ style = SWT.DOUBLE_BUFFERED | style;
+ return Helper.checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
+ }
+
+ private static Table checkNull(Table table) {
+ if (table == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ return table;
+ }
+
+ private void createColumn (final int index) {
+ parent.createColumn (this, index);
+
+ text = "";
+
+ //sortButton = new SortButton(this, SWT.NONE);
+// sortButton.addSelectionListener(new SelectionListener() {
+// @Override
+// public void widgetSelected(SelectionEvent se) {
+// Event e = new Event();
+// e.widget = ((SortButton)se.widget).getParent();
+// notifyListeners(SWT.Selection, e);
+// }
+//
+// @Override
+// public void widgetDefaultSelected(SelectionEvent e) {
+// // TODO Auto-generated method stub
+// }
+//
+// });
+
+ this.setFont(FontResources.COLUMN_FONT);
+ this.setForeground(ColorResources.COLUMN_FONT_COLOR);
+ this.setBackground(ColorResources.COLUMN_BG_COLOR);
+
+ addListeners();
+ }
+
+ private void addListeners() {
+ this.addPaintListener(paintListener);
+ addListener(SWT.MouseEnter, mouseMoveEventListener);
+ addListener(SWT.MouseExit, mouseMoveEventListener);
+ addListener(SWT.MouseMove, mouseMoveEventListener);
+ addControlListener(controlListener);
+ addMouseListener(mouseListener);
+ }
+
+ public void addSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ }
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+ }
+
+ public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ }
+ removeListener (SWT.Selection, listener);
+ removeListener (SWT.DefaultSelection,listener);
+ }
+
+ public void pack () {
+ checkWidget();
+ int w = getPreferredWidth();
+ if (w != width) {
+ setWidth(w);
+ }
+ }
+
+ public Table getParent() {
+ checkWidget();
+ return parent;
+ }
+
+ public int getWidth() {
+ checkWidget();
+ return width;
+ }
+
+ public void setWidth(int width) {
+ checkWidget();
+ if (width < 0) {
+ return;
+ }
+
+ if (width == this.width) {
+ return;
+ }
+
+ this.width = width;
+ setBounds(getLeft(), getBounds().y, width, parent.getColumnHeightSize());
+ parent.updateScrollBars(true);
+ processNextColumnsMoveEvent();
+ }
+
+ public int getAlignment() {
+ checkWidget();
+ if ((style & SWT.LEFT) != 0) {
+ return SWT.LEFT;
+ }
+ if((style & SWT.CENTER) != 0) {
+ return SWT.CENTER;
+ }
+
+ if((style & SWT.RIGHT) != 0) {
+ return SWT.RIGHT;
+ }
+
+ return SWT.LEFT;
+ }
+
+ public void setAlignment(int alignment) {
+ checkWidget();
+ if( (alignment & ( SWT.LEFT | SWT.RIGHT | SWT.CENTER )) != 0 ) {
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ }
+ }
+
+ public boolean getMoveable() {
+ checkWidget();
+ return moveable;
+ }
+
+ public void setMoveable(boolean moveable) {
+ checkWidget();
+ this.moveable = moveable;
+ if (moveable && dnd == null) {
+ dnd = new TableColumnDragAndDrop(this);
+ }
+ }
+
+ public boolean getResizable() {
+ checkWidget();
+ return resizable;
+ }
+
+ public void setResizable(boolean resizable) {
+ checkWidget();
+ this.resizable = resizable;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ this.redraw();
+ }
+
+ public Image getImage() {
+ checkWidget();
+ return image;
+ }
+
+ public void setImage(Image image) {
+ this.image = image;
+ }
+
+ // TODO: for drag and drop
+ public Image getDndImage() {
+ return dndImage;
+ }
+
+ @Override
+ public void setBackground(Color color) {
+ super.setBackground(color);
+ background = color;
+ if (selectedBackground != null) {
+ selectedBackground.dispose();
+ }
+ selectedBackground = new Color(Display.getCurrent(),
+ Math.min(color.getRed() + 15, 255),
+ Math.min(color.getGreen() + 15, 255),
+ Math.min(color.getBlue() + 15, 255));
+
+// if (sortButton != null) {
+// sortButton.setBackground(color);
+// sortButton.setHoverBackground(selectedBackground);
+// }
+ }
+
+ @Override
+ public void setForeground(Color color) {
+ super.setForeground(color);
+ foreground = color;
+ if (selectedForeground != null) {
+ selectedForeground.dispose();
+ }
+ selectedForeground = new Color(Display.getCurrent(),
+ Math.min(color.getRed() - 15, 255),
+ Math.min(color.getGreen() - 15, 255),
+ Math.min(color.getBlue() - 15, 255));
+ }
+
+ @Override
+ public void setFont(Font font) {
+ super.setFont(font);
+ this.font = font;
+ this.selectedFont = font;
+ }
+
+ void relesaeParent() {
+ parent.destroyColumn(this);
+ }
+
+ private void drawColumn(PaintEvent e) {
+ Rectangle rect = ((Canvas)e.widget).getClientArea();
+ dndImage = new Image(Display.getCurrent(), rect.width, rect.height);
+ GC gc = new GC(dndImage);
+
+ // drawing back ground
+ gc.setBackground(isHoverState ? selectedBackground : background);
+ gc.fillRectangle(rect);
+
+ gc.setForeground(ColorResources.DEFAULT_STROKE);
+ gc.setLineWidth(1);
+ gc.drawLine(rect.width-1, 0, rect.width-1, rect.height);
+
+ gc.setForeground(isHoverState ? selectedForeground : foreground);
+
+ if (parent.getSortColumn() == this) {
+ // sort column
+ int x = rect.x + (rect.width - SORT_INDICATOR_WIDTH - SPACING);
+ if (parent.getSortDirection() == SWT.UP) {
+ sortIndicator = ImageResources.SORT_INDICATOR_UP;
+ } else if (parent.getSortDirection() == SWT.DOWN){
+ sortIndicator = ImageResources.SORT_INDICATOR_DOWN;
+ } else {
+ sortIndicator = null;
+ }
+ if (sortIndicator != null) {
+ Rectangle bounds = sortIndicator.getBounds();
+ //sortButton.setBounds(x, 0, SORT_INDICATOR_WIDTH, rect.height);
+ gc.drawImage(sortIndicator, x, rect.y + (rect.height- bounds.height) / 2);
+ }
+ }
+ if (image != null || !text.isEmpty()) {
+ //
+ int imageX = rect.x;
+ int textX = rect.x;
+ int imageY = 0;
+ int textY = 0;
+
+ Point imageEX = new Point(0, 0);
+ if (image != null) {
+ imageEX = new Point(image.getImageData().width,
+ image.getImageData().height);
+ }
+
+ if (needRedrawingText) {
+ int textWidth = TextSizeUtil.textExtent(getFont(), text);
+ drawingText = text;
+ if (textWidth > (rect.width - imageEX.x - 10)) {
+ while (textWidth > (rect.width - 10) - TextSizeUtil.OMITLEN && drawingText.length() > 1) {
+ drawingText = drawingText.substring(0, drawingText.length() - 1);
+ textWidth = TextSizeUtil.textExtent(getFont(), drawingText);
+ }
+ drawingText = drawingText + TextSizeUtil.OMIT;
+ }
+ needRedrawingText = false;
+ }
+
+ int textWidth = TextSizeUtil.textExtent(getFont(), drawingText);
+ switch (getAlignment()) {
+ case SWT.LEFT:
+ imageX += (image != null ? SPACING : 0);
+ textX += imageX + imageEX.x + SPACING;
+ break;
+ case SWT.RIGHT:
+ imageX += (image != null
+ ? rect.width - imageEX.x - SPACING - textWidth - 10
+ : rect.width - textWidth - 10);
+ textX += imageX + imageEX.x + SPACING;
+ break;
+ case SWT.CENTER:
+ imageX += (image != null
+ ? rect.x + ((rect.width - image.getImageData().width - textWidth) / 2)
+ : rect.x + ((rect.width - textWidth) / 2));
+ textX += imageX + imageEX.x;
+ break;
+ }
+
+ if (image != null) {
+ imageY = rect.y + ((rect.height - image.getImageData().height) / 2);
+ gc.drawImage(image, imageX, imageY);
+ }
+
+ int fontHeight = gc.getFontMetrics().getHeight();
+ textY = rect.y + (rect.height - fontHeight) / 2 - 1;
+
+ if (!text.isEmpty()) {
+ gc.setFont(isHoverState? selectedFont : font);
+ gc.drawText(drawingText, textX, textY, true);
+ }
+ }
+
+ e.gc.drawImage(dndImage, 0, 0);
+ gc.dispose();
+ }
+
+ protected PaintListener paintListener = new PaintListener() {
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ drawColumn(e);
+ }
+ };
+
+ protected Listener mouseMoveEventListener = new Listener() {
+
+ @Override
+ public void handleEvent(Event event) {
+ if (!isEnabled()) {
+ return;
+ }
+
+ TableColumn column = (TableColumn) event.widget;
+ if (event.type == SWT.MouseEnter) {
+ isHoverState = true;
+ redraw();
+ } else if (event.type == SWT.MouseExit) {
+ isHoverState = false;
+ if (resizable) {
+ isResizeableState = false;
+ if (setCursor) {
+ setCursor = false;
+ column.setCursor(backupCursor);
+ }
+ }
+ // TODO
+ column.redraw();
+ column.update();
+ } else if (event.type == SWT.MouseMove) {
+ if (!resizable) {
+ return;
+ }
+
+ if (event.x >= (width - RESIZABLE_WIDTH)) {
+ isResizeableState = true;
+ if (!setCursor) {
+ setCursor = true;
+ backupCursor = column.getCursor();
+ column.setCursor(new Cursor(Display.getCurrent(), SWT.CURSOR_SIZEWE));
+ }
+ } else {
+ isResizeableState = false;
+ if (setCursor) {
+ setCursor = false;
+ column.setCursor(backupCursor);
+ }
+ }
+
+ if (isResizedState) {
+ if (event.x > MIN_WIDTH) {
+ setWidth(event.x);
+ redraw();
+ }
+ }
+ }
+ }
+ };
+
+ protected ControlListener controlListener = new ControlListener() {
+
+ @Override
+ public void controlMoved(ControlEvent e) {
+ int left = getLeft();
+ Rectangle rect = new Rectangle(left, 0, width, parent.getColumnHeightSize());
+ setBounds(rect);
+ }
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ needRedrawingText = true;
+ parent.redraw();
+ for (TableItem item : parent.getItems()) {
+ if (item != null) {
+ item.updateSizeAndLocation(getOrderIndex());
+ }
+ }
+ redraw();
+ }
+ };
+
+ protected MouseListener mouseListener = new MouseListener() {
+ @Override
+ public void mouseDoubleClick(MouseEvent e) {
+ if (isResizeableState) {
+ setWidth(getPreferredWidth());
+ redraw();
+ }
+ }
+
+ @Override
+ public void mouseDown(MouseEvent e) {
+ if (e.x > (width - RESIZABLE_WIDTH) || width < MIN_WIDTH) {
+ if (!isResizedState) {
+ isResizedState = true;
+ backupMoveable = moveable;
+ moveable = false;
+ }
+ } else {
+ Event ev = new Event();
+ ev.widget = e.widget;
+ notifyListeners(SWT.Selection, ev);
+ }
+ }
+
+ @Override
+ public void mouseUp(MouseEvent e) {
+ if (isResizedState) {
+ isResizedState = false;
+ moveable = backupMoveable;
+ }
+ }
+ };
+
+ // left offset
+ final int getLeft() {
+ int result = 0;
+ ArrayList<TableColumn> columns = (ArrayList<TableColumn>) parent.getColumnList();
+ int[] columnOrder = parent.getColumnOrder();
+ int orderedIndex = -1;
+ for (int i = 0; orderedIndex == -1 && i < columnOrder.length; i++) {
+ if (columnOrder[i] == parent.indexOf(this)) {
+ orderedIndex = i;
+ }
+ }
+ for (int i = 0; i < orderedIndex; i++) {
+ result += columns.get(columnOrder[i]).getWidth();
+ }
+
+ if (parent.isChecked()) {
+ result += parent.getCheckBoxWidth();
+ }
+ return result;
+ }
+
+ final int getOrderIndex() {
+ int[] columnOrder = parent.getColumnOrder();
+ int orderedIndex = -1;
+ for (int i = 0; orderedIndex == -1 && i < columnOrder.length; i++) {
+ if (columnOrder[i] == parent.indexOf(this)) {
+ orderedIndex = i;
+ break;
+ }
+ }
+ return orderedIndex;
+ }
+
+ final int getPreferredWidth() {
+ int result = 0;
+ Font font = getFont();
+ if (text != null && text.length() >= 0) {
+ if (text.indexOf('\n') != -1) {
+ result = TextSizeUtil.stringExtend(font, text);
+ } else {
+ result = TextSizeUtil.textExtent(font, text);
+ }
+
+ Image image = getImage();
+ if (image != null) {
+ result += image.getBounds().width + SPACING;
+ }
+
+ if (parent.getSortColumn() == this && parent.getSortDirection() != SWT.NONE) {
+ result += SORT_INDICATOR_WIDTH + SPACING;
+ }
+ }
+
+ // Extend computed width if there are wider items
+ int columnIndex = parent.indexOf(this);
+ int itemsPreferredWidth = parent.getItemsPreferredWidth(columnIndex);
+ result = Math.max(result, itemsPreferredWidth);
+
+ result += HEADERPADDING_WIDTH;
+
+ return result;
+ }
+
+ private void processNextColumnsMoveEvent() {
+ int[] columnsOrder = parent.getColumnOrder();
+ boolean found = false;
+ for (int i = 0; i < columnsOrder.length; i++) {
+ TableColumn column = parent.getColumn(columnsOrder[i]);
+ if (column == this) {
+ found = true;
+ } else if (found) {
+ column.notifyListeners(SWT.Move, new Event());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.TransferData;
+
+public class TableColumnDataTransfer extends ByteArrayTransfer {
+ static class TableColumnData {
+ int orderIndex;
+ }
+
+ private static final String TYPE_NAME = "table_column_data_type";
+ private static final int TYPE_ID = registerType(TYPE_NAME);
+ private static TableColumnDataTransfer instance = new TableColumnDataTransfer();
+
+ public static TableColumnDataTransfer getInstance() {
+ return instance;
+ }
+
+ private TableColumnDataTransfer() {
+ }
+
+ public void javaToNative(Object object, TransferData transferData) {
+ if (!checkType(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+
+ TableColumnData columnData = (TableColumnData) object;
+ ByteArrayOutputStream out = null;
+ DataOutputStream writeOut = null;
+
+ try {
+ out = new ByteArrayOutputStream();
+ writeOut = new DataOutputStream(out);
+ writeOut.writeInt(columnData.orderIndex);
+ byte[] buffer = out.toByteArray();
+ super.javaToNative(buffer, transferData);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (writeOut != null) {
+ try {
+ writeOut.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData)) {
+ return null;
+ }
+
+ byte[] buffer = (byte[]) super.nativeToJava(transferData);
+ if (buffer == null) {
+ return null;
+ }
+
+ TableColumnData columnData = null;
+ ByteArrayInputStream in = null;
+ DataInputStream readIn = null;
+
+ try {
+ in = new ByteArrayInputStream(buffer);
+ readIn = new DataInputStream(in);
+ columnData = new TableColumnData();
+ columnData.orderIndex = readIn.readInt();
+ readIn.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } finally {
+ if (readIn != null) {
+ try {
+ readIn.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return columnData;
+ }
+
+ protected String[] getTypeNames() {
+ return new String[] { TYPE_NAME };
+ }
+
+ protected int[] getTypeIds() {
+ return new int[] { TYPE_ID };
+ }
+
+ boolean checkType(Object object) {
+ if (object == null || !(object instanceof TableColumnData)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ protected boolean validate(Object object) {
+ return checkType(object);
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.DropTargetAdapter;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.widgets.Event;
+import org.tizen.emulator.manager.ui.table.TableColumnDataTransfer.TableColumnData;
+
+public class TableColumnDragAndDrop {
+ private TableColumn column;
+
+ public TableColumnDragAndDrop(final TableColumn column) {
+ this.column = column;
+
+ DragSource ds = new DragSource(column, DND.DROP_MOVE);
+ ds.setTransfer(new Transfer[] {TableColumnDataTransfer.getInstance()});
+ ds.addDragListener(sourceAdapter);
+
+ DropTarget dt = new DropTarget(column, DND.DROP_MOVE);
+ dt.setTransfer(new Transfer[] {TableColumnDataTransfer.getInstance()});
+ dt.addDropListener(targetAdapter);
+ }
+
+ private DragSourceAdapter sourceAdapter = new DragSourceAdapter() {
+ public void dragStart(DragSourceEvent event) {
+ // TODO
+ event.image = column.getDndImage();
+
+ if (!column.getMoveable()) {
+ event.doit = false;
+ }
+ }
+
+ public void dragSetData(DragSourceEvent event) {
+ // send order index to target
+ int index = column.getParent().indexOf(column);
+ int[] columnOrder = column.getParent().getColumnOrder();
+ int orderIndex = -1;
+ for (int i = 0; i< columnOrder.length; i++) {
+ if (columnOrder[i] == index) {
+ orderIndex = i;
+ break;
+ }
+ }
+
+ TableColumnData data = new TableColumnData();
+ data.orderIndex = orderIndex;
+ TableColumnDataTransfer.getInstance().javaToNative(data, event.dataType);
+ event.data = data;
+ }
+ };
+
+ private DropTargetAdapter targetAdapter = new DropTargetAdapter() {
+ public void dragEnter(DropTargetEvent event) {
+ // TODO
+ // draw guide icon
+ }
+ public void dragLeave(DropTargetEvent event) {
+ // TODO
+ }
+
+ public void dragOver(DropTargetEvent event) {
+ event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_INSERT_BEFORE;
+ }
+
+ public void drop(DropTargetEvent event) {
+ TableColumnData data = (TableColumnData)TableColumnDataTransfer.getInstance()
+ .nativeToJava(event.currentDataType);
+
+ int sourceOrderIndex = data.orderIndex;
+ int index = column.getParent().indexOf(column);
+ int[] columnOrder = column.getParent().getColumnOrder();
+ int sourceIndex = columnOrder[sourceOrderIndex];
+ int targetOrderIndex = -1;
+ for (int i = 0; i< columnOrder.length; i++) {
+ if (columnOrder[i] == index) {
+ targetOrderIndex = i;
+ break;
+ }
+ }
+
+ if (sourceOrderIndex > targetOrderIndex) {
+ for (int i = sourceOrderIndex; i > targetOrderIndex; i--) {
+ columnOrder[i] = columnOrder[i-1];
+ }
+ } else {
+ for (int i = sourceOrderIndex; i < targetOrderIndex; i++) {
+ columnOrder[i] = columnOrder[i+1];
+ }
+ }
+
+ columnOrder[targetOrderIndex] = sourceIndex;
+ column.getParent().setColumnOrder(columnOrder);
+
+ for (int i = 0; i < columnOrder.length; i++) {
+ TableColumn c = column.getParent().getColumn(columnOrder[i]);
+ c.notifyListeners(SWT.Move, new Event());
+ }
+ }
+ };
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+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.Event;
+import org.eclipse.swt.widgets.Listener;
+
+public class TableItem extends Canvas {
+ private static final class Data {
+ String text = "";
+ Image image;
+ private Image selectedImage;
+ Font font;
+ Color backgroundColor;
+ Color foregroundColor;
+
+ int textWidth = -1;
+ boolean needRedrawingText = true;
+ String drawingText = "";
+ }
+
+ private Table parent;
+ private Data[] dataList;
+ private Font font;
+ private Color background;
+ private Color selectedBackground;
+ //private Color focusOutSelectedBackground;
+ private Color foreground;
+ private Color selectedForeground;
+
+ private boolean checked;
+ private boolean grayed;
+ private int index;
+
+ //private boolean isHoverState = false;
+ private boolean isSelected = false;
+
+ private CheckBoxButton checkBox;
+
+ public TableItem(Table parent, int style) {
+ this(parent, style, checkNull (parent).getItemCount());
+ }
+
+ public TableItem(final Table parent, int style, int index) {
+ super(parent.tableItem, style);
+ this.parent = parent;
+ this.index = index;
+
+ parent.createItem(this, index);
+
+ setFont(FontResources.ITEM_FONT);
+ setForeground(ColorResources.ITEM_FONT_COLOR);
+ if ((index % 2) == 0) {
+ setBackground(ColorResources.ITEM_BG_COLOR_EVEN);
+ } else {
+ setBackground(ColorResources.ITEM_BG_COLOR_ODD);
+ }
+
+ selectedForeground = ColorResources.ITEM_SELECTED_FONT_COLOR;
+ selectedBackground = ColorResources.ITEM_SELECTED_BG_COLOR;
+ //focusOutSelectedBackground = ColorResources.ITEM_FOCUST_OUT_SELECTED_BG_COLOR;
+
+ if (parent.isChecked()) {
+ checkBox = new CheckBoxButton(this, SWT.None);
+ checkBox.setBackground(background);
+ checkBox.setSelectedBackground(selectedBackground);
+ }
+
+ addListeners();
+ }
+
+ private void addListeners() {
+ this.addListener(SWT.MouseDown, mouseEventListener);
+ this.addControlListener(controlListener);
+ this.addPaintListener(paintListener);
+ if (parent.isChecked()) {
+ checkBox.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ parent._select(index);
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+ }
+
+ public Table getParent() {
+ checkWidget();
+ return parent;
+ }
+
+ public void setBackground(Color color) {
+ checkWidget();
+ if (color != null && color.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ if (!equals(background, color)) {
+ background = color;
+ parent.redraw();
+ }
+ }
+
+ public void setBackground(int index, Color color) {
+ checkWidget();
+ if (color != null && color.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int count = Math.max(1, parent.getColumnCount());
+ if (index >= 0 && index < count) {
+ ensureData(index, count);
+ if (!equals(dataList[index].backgroundColor, color)) {
+ dataList[index].backgroundColor = color;
+ parent.redraw();
+ }
+ }
+ }
+
+ public Color getBackground() {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ if (background == null) {
+ return parent.getBackground();
+ } else {
+ return background;
+ }
+ }
+
+ public Color getBackground(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if(hasData(index) && dataList[index].backgroundColor != null) {
+ return dataList[index].backgroundColor;
+ }
+
+ return getBackground();
+ }
+
+ public void setFont(Font font) {
+ checkWidget();
+ if (font != null && font.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ if (!equals(this.font, font)) {
+ this.font = font;
+ clearTextWidth();
+ if (parent.getColumnCount() == 0) {
+ parent.updateScrollBars(true);
+ }
+ parent.redraw();
+ }
+ }
+
+ public void setFont(int index, Font font) {
+ checkWidget();
+ if (font != null && font.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int count = Math.max(1, parent.getColumnCount());
+ if (index >= 0 && index < count) {
+ ensureData(index, count);
+ Data data = dataList[index];
+ if (!equals(font, data.font)) {
+ data.font = font;
+ data.textWidth = -1;
+ parent.redraw();
+ }
+ }
+ }
+
+ public Font getFont() {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ if (font == null) {
+ return parent.getFont();
+ }
+ return font;
+ }
+
+ public Font getFont(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if (hasData(index) && dataList[index].font != null) {
+ return dataList[index].font;
+ }
+ return getFont();
+ }
+
+ public void setForeground(Color color) {
+ checkWidget();
+ if (color != null && color.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ if (!equals(foreground, color)) {
+ foreground = color;
+ parent.redraw();
+ }
+ }
+
+ public void setForeground(int index, Color color) {
+ checkWidget();
+ if (color != null && color.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int count = Math.max(1, parent.getColumnCount());
+ if (index >= 0 && index < count) {
+ ensureData(index, count);
+ if (!equals(dataList[index].foregroundColor, color)) {
+ dataList[index].foregroundColor = color;
+ parent.redraw();
+ }
+ }
+ }
+
+ public Color getForeground() {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ if (foreground == null) {
+ return parent.getForeground();
+ } else {
+ return foreground;
+ }
+ }
+
+ public Color getForeground(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if(hasData(index) && dataList[index].foregroundColor != null) {
+ return dataList[index].foregroundColor;
+ }
+
+ return getForeground();
+ }
+
+ public void setChecked(boolean checked) {
+ checkWidget();
+ if ((parent.getStyle() & SWT.CHECK) != 0) {
+ this.checked = checked;
+ checkBox.setSelection(checked);
+ }
+ }
+
+ public boolean getChecked() {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if ((parent.getStyle() & SWT.CHECK) != 0) {
+ return checked;
+ }
+ return false;
+ }
+
+ public void setGrayed(boolean grayed) {
+ checkWidget();
+ if ((parent.getStyle() & SWT.CHECK) != 0) {
+ this.grayed = grayed;
+ }
+ }
+
+ /**
+ *
+ * @return the grayed state of the check box
+ */
+ public boolean getGrayed() {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if ((parent.getStyle() & SWT.CHECK) != 0) {
+ return grayed;
+ }
+ return false;
+ }
+
+ public void setImage(Image image) {
+ checkWidget();
+ setImage(0, image);
+ }
+
+ public void setImage (int index, Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int count = Math.max(1, parent.getColumnCount());
+ if (index >= 0 && index < count) {
+ ensureData(index, count);
+ if (!equals(dataList[index].image, image)) {
+ //parent.updateColumnImageCount(index, dataList[index].image, image);
+ dataList[index].image = image;
+ //parent.updateImageImageSize(image);
+ if (parent.getColumnCount() == 0) {
+ parent.updateScrollBars(true);
+ }
+ parent.redraw();
+ }
+ }
+ }
+
+ public void setImage(Image[] images) {
+ checkWidget();
+ if (images == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ for (int i = 0; i < images.length; i++) {
+ if (images[i] != null && images[i].isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+
+ for (int i = 0; i < images.length; i++) {
+ setImage(i, images[i]);
+ }
+ }
+
+ public Image getImage() {
+ checkWidget();
+ return getImage(0);
+ }
+
+ public Image getImage(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ if (hasData(index)) {
+ return dataList[index].image;
+ }
+ return null;
+ }
+
+ public void setSelectedImage(int index, Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int count = Math.max(1, parent.getColumnCount());
+ if (index >= 0 && index < count) {
+ ensureData(index, count);
+ if (!equals(dataList[index].selectedImage, image)) {
+ dataList[index].selectedImage = image;
+ if (parent.getColumnCount() == 0) {
+ parent.updateScrollBars(true);
+ }
+ parent.redraw();
+ }
+ }
+ }
+
+ public Image getSelectedImage(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ if (hasData(index)) {
+ return dataList[index].selectedImage;
+ }
+ return null;
+ }
+
+ public void setText (String text) {
+ checkWidget();
+ setText(0, text);
+ }
+
+ public void setText (int index, String text) {
+ checkWidget();
+ if (text == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ int count = Math.max(1, parent.getColumnCount());
+ if (index >= 0 && index < count) {
+ ensureData(index, count);
+ if (!text.equals(dataList[index].text)) {
+ dataList[index].text = text;
+ dataList[index].textWidth = TextSizeUtil.textExtent(font, text);
+ if (parent.getColumnCount() == 0) {
+ parent.updateScrollBars(true);
+ }
+ parent.redraw();
+ }
+ }
+ }
+
+ public void setText (String [] textList) {
+ checkWidget();
+ if (textList == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ for (int i = 0; i < textList.length; i++) {
+ if (textList[i] != null) {
+ setText(i, textList[i]);
+ }
+ }
+ }
+
+ public String getText() {
+ checkWidget();
+ return getText(0);
+ }
+
+ public String getText(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+ if (hasData(index)) {
+ return dataList[index].text;
+ }
+ return "";
+ }
+
+ public Rectangle getBounds() {
+ return getBounds(0);
+ }
+
+ public Rectangle getBounds(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ Rectangle result = null;
+ int columnCount = parent.getColumnCount();
+ if (columnCount > 0 &&
+ (index < 0 || index >= columnCount)) {
+ result = new Rectangle(0, 0, 0, 0);
+ } else {
+ int left = getLeft(index);
+ int top = getTop(parent.indexOf(this));
+ int width = 0;
+ if (index == 0 && columnCount == 0) {
+ int spacing = getSpacing(index);
+ int paddingWidth = parent.getCellPadding().width;
+ width = getImageWidth(index) + spacing
+ + getTextWidth(index, font) + paddingWidth;
+ } else if (index >= 0 && index < columnCount) {
+ width = parent.getColumn(index).getWidth();
+ }
+
+ int height = getHeight();
+ result = new Rectangle(left, top, width, height);
+ }
+ return result;
+ }
+
+ public Rectangle getImageBounds(int index) {
+ checkWidget();
+ if (!parent.checkData(this, parent.indexOf(this))) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ int itemIndex = parent.indexOf(this);
+ Rectangle cellPadding = parent.getCellPadding();
+ int left = getLeft(index) + cellPadding.x;
+ int top = getTop(itemIndex);
+ int width = getImageWidth(index);
+ int height = getHeight();
+ return new Rectangle(left, top, width, height);
+ }
+
+ // TODO
+ public int getImageIndent() {
+ checkWidget();
+ return 0;
+ }
+
+ public Rectangle getTextBounds(int index) {
+ checkWidget();
+ if (index < -1 || index > parent.getColumnCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int itemIndex = parent.indexOf(this);
+ if (!parent.checkData(this, itemIndex)) {
+ SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ if (index == 0 && parent.getColumnCount() == 0) {
+ index = 0;
+ }
+
+
+ Rectangle cellPadding = parent.getCellPadding();
+ int left = 0;
+ int top = 0;
+ int width = 0;
+ int imageWidth = 0;
+ int height = getHeight();
+
+ if (parent.hasColumnImages(index)) {
+ imageWidth = parent.getColumn(index).getImage().getBounds().width;
+ }
+
+ int spacing = getSpacing(index);
+ left = getLeft(index) + cellPadding.x + imageWidth + spacing;
+ top = getTop(itemIndex);
+ if (index == 0) {
+ width = getTextWidth(0, getFont());
+ } else {
+ width = getColumnWidth(index) - cellPadding.width - imageWidth - spacing;
+ }
+ if (width < 0) {
+ width = 0;
+ }
+
+ return new Rectangle(left, top, width, height);
+ }
+
+ public void clear() {
+ dataList = null;
+ checked = false;
+ grayed = false;
+ parent.updateScrollBars(true);
+ if ((parent.getStyle() & SWT.VERTICAL) != 0) {
+ parent.redraw();
+ }
+ }
+
+ public void setIndex(int i) {
+ this.index = i;
+ if ((index % 2) == 0) {
+ setBackground(ColorResources.ITEM_BG_COLOR_EVEN);
+ } else {
+ setBackground(ColorResources.ITEM_BG_COLOR_ODD);
+ }
+ if (parent.isChecked() && checkBox != null) {
+ checkBox.setBackground(getBackground());
+ }
+ }
+
+ final void shiftData(int index) {
+ if (dataList != null && dataList.length > index
+ && parent.getColumnCount() > 1) {
+ Data[] newDataList = new Data[dataList.length + 1];
+ System.arraycopy(dataList, 0, newDataList, 0, index);
+ int offset = dataList.length - index;
+ System.arraycopy(dataList, index, newDataList, index + 1, offset);
+ dataList = newDataList;
+ }
+ }
+
+ final void removeData(int index) {
+ if (dataList != null && dataList.length > index
+ && parent.getColumnCount() > 1) {
+ Data[] newDataList = new Data[dataList.length - 1];
+ System.arraycopy(dataList, 0, newDataList, 0, index);
+ int offset = dataList.length - index - 1;
+ System.arraycopy(dataList, index + 1, newDataList, index, offset);
+ dataList = newDataList;
+ }
+ }
+
+ private int getColumnWidth(int index) {
+ TableColumn column = parent.getColumn(index);
+ return column.getWidth();
+ }
+
+ private int getLeft(int index) {
+ int result = 0;
+ int columnCount = parent.getColumnCount();
+ if (index == 0 && columnCount == 0) {
+ result = parent.getLeftOffset();
+ } else if (index >= 0 && index < columnCount){
+ int columnLeft = parent.getColumn(index).getLeft();
+ result = columnLeft - parent.getColumnLeftOffset(index);
+ }
+ return result;
+ }
+
+ private int getTop(int index) {
+ int upperItems = index - parent.getTopIndex();
+ int itemHeight = parent.getItemHeight();
+ int result = 0;
+ if (parent.getSelectionCount() == 1) {
+ int select = parent.getSelectionIndex();
+ if (index > select) {
+ result = (upperItems-1) * itemHeight + parent.getSelectedItemHeight();
+ } else {
+ result = upperItems * itemHeight;
+ }
+ } else {
+ result = upperItems * itemHeight;
+ }
+ return result;
+ }
+
+ private int getHeight() {
+ if (parent.getSelectionCount() == 1
+ && parent.getSelectionIndex() == index) {
+ return parent.getSelectedItemHeight();
+ } else {
+ return parent.getItemHeight();
+ }
+ }
+
+ final int getPackWidth(int index) {
+ return getImageWidth(index)
+ + getSpacing(index)
+ + getTextWidth(index, parent.getFont())
+ + parent.getCellPadding().width;
+ }
+
+ private int getImageWidth(int index) {
+ Image image = getImage(index);
+ if (image != null) {
+ return image.getImageData().width;
+ }
+ return 0;
+ }
+
+ private int getTextWidth(int index, Font font) {
+ if (hasData(index)) {
+ Data data = dataList[index];
+ if (data.textWidth == -1) {
+ data.textWidth
+ = TextSizeUtil.stringExtend(font, data.text);
+ }
+ return data.textWidth;
+ }
+ return 0;
+ }
+
+ private void clearTextWidth() {
+ if (dataList != null) {
+ for (Data data : dataList) {
+ if (data != null) {
+ data.textWidth = -1;
+ }
+ }
+ }
+ }
+
+ private int getSpacing(int index) {
+ if (parent.hasColumnImages(index)) {
+ return parent.getCellSpacing();
+ }
+ return 0;
+ }
+
+ ////
+ //// help function
+ ///
+
+ private void ensureData(int index, int columnCount) {
+ if (dataList == null) {
+ dataList = new Data[columnCount];
+ } else if (dataList.length < columnCount) {
+ Data[] newDataList = new Data[columnCount];
+ System.arraycopy(dataList, 0, newDataList, 0, dataList.length);
+ dataList = newDataList;
+ }
+
+ if (dataList[index] == null) {
+ dataList[index] = new Data();
+ }
+ }
+
+ private boolean hasData(int index) {
+ return dataList != null && index >= 0
+ && index < dataList.length && dataList[index] != null;
+ }
+
+ private static Table checkNull (Table control) {
+ if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return control;
+ }
+
+ private static boolean equals(Object obj1, Object obj2) {
+ if (obj1 == obj2) {
+ return true;
+ } else if (obj1 == null) {
+ return false;
+ } else {
+ return obj1.equals(obj2);
+ }
+ }
+
+ void updateLocation(int columnIndex) {
+ Rectangle rect = this.getClientArea();
+ setBounds(new Rectangle(rect.x, getTop(index), rect.width, rect.height));
+ }
+
+ void updateSizeAndLocation(int columnIndex) {
+ if (columnIndex > -1 && dataList[columnIndex] != null) {
+ dataList[columnIndex].needRedrawingText = true;
+ }
+
+ int width = 0;
+ for (int i = 0; i < parent.getColumnCount(); i++) {
+ width += getBounds(i).width;
+ }
+
+ width = Math.max(width, parent.getWidth());
+ int top = getTop(index);
+ setBounds(new Rectangle(0, top, width, getHeight()));
+ }
+
+ protected ControlListener controlListener = new ControlListener() {
+ @Override
+ public void controlMoved(ControlEvent e) {
+ redraw();
+ }
+ @Override
+ public void controlResized(ControlEvent e) {
+ redraw();
+ }
+ };
+
+ protected Listener mouseEventListener = new Listener() {
+
+ @Override
+ public void handleEvent(Event event) {
+ switch(event.type) {
+ /*
+ case SWT.MouseEnter:
+ isHoverState = true;
+ redraw();
+ break;
+ case SWT.MouseExit:
+ isHoverState = false;
+ redraw();
+ break;
+ */
+ case SWT.MouseDown:
+ parent._select(index);
+ break;
+ default:
+ break;
+ }
+ }
+
+ };
+
+ private Rectangle clientArea;
+ protected PaintListener paintListener = new PaintListener() {
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ clientArea = ((Canvas)e.widget).getClientArea();
+ GC gc = e.gc;
+ isSelected = parent.isSelected(index);
+ if (isSelected) {
+ //if (parent.isFocusControl()) {
+ gc.setBackground(selectedBackground);
+ //} else {
+ // gc.setBackground(focusOutSelectedBackground);
+ //}
+ } else {
+ gc.setBackground(background);
+ }
+ gc.fillRectangle(clientArea);
+
+ if (parent.isChecked()) {
+ drawCheckBox(e);
+ }
+
+ int leftOffset = parent.isChecked() ? parent.getCheckBoxWidth() : 0;
+ drawItem(e, 0, leftOffset);
+ for (int i = 1; i < parent.getColumnCount(); i++) {
+ leftOffset += getBounds(i-1).width;
+ drawItem(e, i, leftOffset);
+ }
+ }
+ };
+
+ private void drawCheckBox(PaintEvent e) {
+ if (clientArea == null) {
+ return;
+ }
+ GC gc = e.gc;
+ int width = parent.getCheckBoxWidth();
+ Rectangle drawingRect = new Rectangle(clientArea.x, clientArea.y, width, clientArea.height);
+ gc.setClipping(drawingRect);
+
+ checkBox.setBounds(drawingRect.x, drawingRect.y, width - 1, drawingRect.height);
+ if (isSelected) {
+ checkBox.setSelection(true);
+ } else {
+ checkBox.setSelection(false);
+ }
+ gc.setForeground(ColorResources.DEFAULT_STROKE);
+ gc.setLineWidth(1);
+ gc.drawLine(width - 1, 0, width - 1, clientArea.height);
+ }
+
+ private void drawItem(PaintEvent e, int index, int leftOffset) {
+ if (clientArea == null) {
+ return;
+ }
+ GC gc = e.gc;
+ int width = getBounds(index).width;
+ Rectangle drawingRect = new Rectangle(clientArea.x + leftOffset, clientArea.y, width, clientArea.height);
+ gc.setClipping(drawingRect);
+
+ if (dataList[index] != null) {
+ int imageX = clientArea.x;
+ int textX = clientArea.x;
+ int imageY = 0;
+ int textY = 0;
+
+ Point imageEX = new Point(0, 0);
+ Image image = null;
+ if (isSelected && parent.getSelectionCount() == 1) {
+ image = getSelectedImage(index);
+ } else {
+ image = getImage(index);
+ }
+ if (image != null) {
+ imageEX = new Point(image.getImageData().width,
+ image.getImageData().height);
+ }
+
+ String drawingText = dataList[index].drawingText;
+ if (dataList[index].needRedrawingText) {
+ drawingText = getText(index);
+ int textWidth = TextSizeUtil.textExtent(getFont(), drawingText);
+ if (textWidth > (drawingRect.width - imageEX.x - 10)) {
+ while((textWidth > (drawingRect.width - 10) - TextSizeUtil.OMITLEN)
+ && drawingText.length() > 1) {
+ drawingText = drawingText.substring(0, drawingText.length() - 1);
+ textWidth = TextSizeUtil.textExtent(getFont(), drawingText);
+ }
+ drawingText = drawingText + TextSizeUtil.OMIT;
+ }
+ dataList[index].needRedrawingText = false;
+ dataList[index].drawingText = drawingText;
+ }
+
+ int textWidth = TextSizeUtil.textExtent(getFont(), drawingText);
+ switch(parent.getColumn(index).getAlignment()) {
+ case SWT.LEFT:
+ imageX += (image != null
+ ? leftOffset + 5
+ : leftOffset + 5);
+ textX += imageX + imageEX.x + 5;
+ break;
+ case SWT.RIGHT:
+ imageX += (image != null
+ ? leftOffset + drawingRect.width - imageEX.x -2 - textWidth - 10
+ : leftOffset + drawingRect.width - textWidth - 10);
+ textX += imageX + imageEX.x + 5;
+ break;
+ case SWT.CENTER:
+ imageX += (image != null
+ ? leftOffset + (drawingRect.width - image.getImageData().width - textWidth) / 2
+ : leftOffset + (drawingRect.width - textWidth) / 2);
+ textX += imageX + imageEX.x;
+ break;
+ default:
+ }
+
+ if (image != null) {
+ imageY = drawingRect.y + ((drawingRect.height - image.getImageData().height)/2);
+ gc.drawImage(image, imageX, imageY);
+ }
+
+ if (getText(index) != null && !getText(index).isEmpty()) {
+ gc.setFont(font);
+ textY = drawingRect.y + (drawingRect.height - gc.getFontMetrics().getHeight())/2 - 1;
+ gc.setForeground(isSelected ? selectedForeground : foreground);
+ gc.drawText(drawingText, textX, textY);
+ }
+ }
+ gc.setForeground(ColorResources.DEFAULT_STROKE);
+ gc.setLineWidth(1);
+ gc.drawLine(leftOffset + width - 1, 0, leftOffset + width -1, drawingRect.height);
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+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;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+
+import com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBar;
+
+public class TableScrolledComposite extends Composite {
+ Control tableContent;
+ Control tableItemContent;
+ Listener contentListener;
+ Listener filter;
+
+ int minHeight = 0;
+ int minWidth = 0;
+
+ FlatScrollBar vBar;
+ FlatScrollBar hBar;
+
+ private int scrollBarWidth = 6;
+
+ public TableScrolledComposite(Composite parent, int style) {
+ super(parent, checkStyle(style));
+ super.setLayout(new TableScrolledCompositeLayout());
+
+ if ((style & SWT.VERTICAL) != 0) {
+ vBar = new FlatScrollBar(this, SWT.VERTICAL);
+ if (vBar != null) {
+ vBar.setVisible(false);
+ vBar.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ vScroll();
+ }
+ });
+ }
+ }
+
+ if ((style & SWT.HORIZONTAL) != 0) {
+ hBar = new FlatScrollBar(this, SWT.HORIZONTAL);
+ if (hBar != null) {
+ hBar.setVisible(false);
+ hBar.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ hScroll();
+ }
+ });
+ }
+ }
+
+ contentListener = new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ if (event.type == SWT.Resize) {
+ layout(false);
+ }
+ }
+ };
+ }
+
+ private static int checkStyle (int style) {
+ int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ return style & mask;
+ }
+
+ boolean contains(Control control) {
+ if (control == null || control.isDisposed()) {
+ return false;
+ }
+
+ Composite parent = control.getParent();
+ while (parent != null && !(parent instanceof Shell)) {
+ if (this == parent) return true;
+ parent = parent.getParent();
+ }
+
+ return false;
+ }
+
+ public Control getContent() {
+ return tableContent;
+ }
+
+ public Point getOrigin() {
+ checkWidget();
+ if (tableContent == null) {
+ return new Point(0, 0);
+ }
+ Point location = tableContent.getLocation();
+ return new Point(-location.x, -location.y);
+ }
+
+ public void setOrigin(Point origin) {
+ setOrigin(origin.x, origin.y);
+ }
+
+ public void setOrigin(int x, int y) {
+ checkWidget();
+ if (tableContent == null) return;
+ if (hBar != null) {
+ hBar.setSelection(x);
+ hBar.notifyListeners(SWT.None);
+ x = -hBar.getSelection();
+ } else {
+ x = 0;
+ }
+
+ if (vBar != null) {
+ vBar.setSelection(y);
+ hBar.notifyListeners(SWT.None);
+ y = -vBar.getSelection();
+ } else {
+ y = 0;
+ }
+ tableContent.setLocation(x, 0);
+ }
+
+ public void setTableItemContent(Control content) {
+ this.tableItemContent = content;
+ }
+
+ public void setContent(Control content) {
+ checkWidget();
+ if (this.tableContent != null && !this.tableContent.isDisposed()) {
+ this.tableContent.removeListener(SWT.Resize, contentListener);
+ this.tableContent.setBounds(new Rectangle(-200, -200, 0, 0));
+ }
+
+ this.tableContent = content;
+
+ if (this.tableContent != null) {
+
+ if (vBar != null) {
+ vBar.setMaximum (0);
+ vBar.setThumb (0);
+ vBar.setSelection(0);
+ vBar.notifyListeners(SWT.None);
+ }
+ if (hBar != null) {
+ hBar.setMaximum (0);
+ hBar.setThumb (0);
+ hBar.setSelection(0);
+ hBar.notifyListeners(SWT.None);
+ }
+
+ layout(false);
+ this.tableContent.addListener(SWT.Resize, contentListener);
+
+ } else {
+ if (hBar != null) {
+ hBar.setVisible(false);
+ }
+ if (vBar != null) {
+ vBar.setVisible(false);
+ }
+ }
+ }
+
+ boolean needVScroll(Rectangle contentRect, boolean hVisible) {
+ if (vBar == null) {
+ return false;
+ }
+ boolean result = false;
+ Rectangle hostRect = getBounds();
+ //int border = getBorderWidth();
+ //hostRect.height -= 2 * border;
+
+ if(hostRect.height != contentRect.height) {
+ if (hVisible && hBar != null) {
+ hostRect.height -= hBar.getSize().y;
+ }
+ }
+
+ if (contentRect.height > hostRect.height) {
+ result = true;
+ }
+
+ return result;
+ }
+
+ void vScroll() {
+ if (tableItemContent == null) return;
+ Point location = tableItemContent.getLocation ();
+ int vSelection = vBar.getSelection();
+ tableItemContent.setLocation (location.x, -vSelection);
+ }
+
+ boolean needHScroll(Rectangle contentRect, boolean vVisible) {
+ if (hBar == null) {
+ return false;
+ }
+
+ boolean result = false;
+ Rectangle hostRect = getBounds();
+ //int border = getBorderWidth();
+ //hostRect.width -= 2 * border;
+
+ if (hostRect.width != contentRect.width) {
+ if (vVisible && vBar != null) {
+ hostRect.width -= vBar.getSize().x;
+ }
+ }
+
+ if (contentRect.width > hostRect.width) {
+ result = true;
+ }
+
+ return result;
+ }
+
+ void hScroll() {
+ if (tableContent == null) return;
+ Point location = tableContent.getLocation ();
+ int hSelection = hBar.getSelection();
+ tableContent.setLocation (-hSelection, location.y);
+ }
+
+ public void setMinSize(Point size) {
+ if (size == null) {
+ setMinSize(0, 0);
+ } else {
+ setMinSize(size.x, size.y);
+ }
+ }
+
+ public void setMinSize(int width, int height) {
+ checkWidget();
+ if (width == minWidth && height == minHeight) {
+ return;
+ }
+
+ minWidth = Math.max(0, width);
+ minHeight = Math.max(0, height);
+ layout(false);
+ }
+
+ public void showControl(Control control) {
+ checkWidget();
+ if (control == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (control.isDisposed()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (!contains(control)) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ Rectangle itemRect = getDisplay().map(control.getParent(), this, control.getBounds());
+ Rectangle area = getClientArea();
+ Point origin = getOrigin();
+
+ if (itemRect.x < 0) {
+ origin.x = Math.max(0, origin.x + itemRect.x);
+ } else {
+ if (area.width < itemRect.x + itemRect.width) {
+ origin.x = Math.max(0,
+ origin.x + itemRect.x
+ + Math.min(itemRect.width, area.width)
+ - area.width);
+ }
+ }
+
+ if (itemRect.y < 0) {
+ origin.y = Math.max(0, origin.y + itemRect.y);
+ } else {
+ if (area.height < itemRect.y + itemRect.height) {
+ origin.y = Math.max(0,
+ origin.y + itemRect.y
+ + Math.min(itemRect.height, area.height)
+ - area.height);
+ }
+ }
+
+ setOrigin(origin);
+ }
+
+ public int getScrollBarWidth() {
+ return scrollBarWidth;
+ }
+
+ public void setScrollBarWidth(int scrollBarWidth) {
+ this.scrollBarWidth = scrollBarWidth;
+ }
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+
+import com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBar;
+
+public class TableScrolledCompositeLayout extends Layout {
+ boolean inLayout = false;
+ static final int DEFAULT_WIDTH = 64;
+ static final int DEFAULT_HEIGHT = 64;
+
+ private FlatScrollBar hBar;
+ private FlatScrollBar vBar;
+
+ @Override
+ protected Point computeSize(Composite composite, int wHint, int hHint,
+ boolean flushCache) {
+ TableScrolledComposite sc = (TableScrolledComposite)composite;
+ Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ if (sc.tableContent != null) {
+ Point currentSize = sc.tableContent.getSize();
+ size.x = currentSize.x;
+ size.y = currentSize.y;
+ }
+ size.x = Math.max(size.x, sc.minWidth);
+ size.y = Math.max(size.y, sc.minHeight);
+ if (wHint != SWT.DEFAULT) size.x = wHint;
+ if (hHint != SWT.DEFAULT) size.y = hHint;
+ return size;
+ }
+
+ @Override
+ protected void layout(Composite composite, boolean flushCache) {
+ if (inLayout) {
+ return;
+ }
+ TableScrolledComposite sc = (TableScrolledComposite)composite;
+ if (sc.tableContent == null) {
+ return;
+ }
+
+ Rectangle hostRect = sc.getClientArea();
+ hBar = sc.hBar;
+ vBar = sc.vBar;
+ if (hBar != null) {
+ if (hBar.getSize().y >= hostRect.height) {
+ return;
+ }
+ }
+ if (vBar != null) {
+ if (vBar.getSize().x >= hostRect.width) {
+ return;
+ }
+ }
+
+ inLayout = true;
+ Rectangle tableRect = sc.tableContent.getBounds();
+ Rectangle tableItemRect = sc.tableItemContent.getBounds();
+
+ boolean hVisible = sc.needHScroll(tableRect, false);
+ boolean vVisible = sc.needVScroll(tableItemRect, hVisible);
+ int scrollBarWidth = sc.getScrollBarWidth();
+
+ if (!hVisible && vVisible) {
+ hVisible = sc.needHScroll(tableRect, vVisible);
+ }
+ if (hBar != null) {
+ hBar.setVisible(hVisible);
+ if (hVisible) {
+ hBar.setBounds(0, hostRect.height-scrollBarWidth,
+ hostRect.width, scrollBarWidth);
+ } else {
+ hBar.setBounds(0, 0, 0, 0);
+ }
+ }
+ if (vBar != null) {
+ vBar.setVisible(vVisible);
+ if (vVisible) {
+ // 30 is table column height
+ vBar.setBounds(hostRect.width - scrollBarWidth, 30, scrollBarWidth,
+ (hVisible ? hostRect.height - 30 - scrollBarWidth
+ : hostRect.height - 30));
+ } else {
+ vBar.setBounds(0, 0, 0, 0);
+ }
+ }
+
+// boolean isChangeTableRect = false;
+// boolean isChangeTableItemRect = false;
+ GC gc = new GC (sc);
+ if (hBar != null && hBar.isVisible()) {
+ int hPage = tableRect.width - hostRect.width;
+ hBar.setMaximum(hPage);
+ hBar.setIncrementButtonLength(6);
+ hBar.setIncrement(gc.getFontMetrics().getAverageCharWidth());
+ hBar.setPageIncrement(hostRect.width / 2);
+ int hSelection = hBar.getSelection ();
+ if (hSelection >= hPage) {
+ if (hPage <= 0) {
+ hSelection = 0;
+ hBar.setSelection(0);
+ }
+ tableRect.x = -hSelection;
+ }
+ }
+
+ // using tableItemRect
+ if (vBar != null && vBar.isVisible()) {
+ int vPage = tableItemRect.height - hostRect.height;
+ vBar.setMaximum(vPage);
+ //vBar.setIncrement(30);
+ vBar.setIncrementButtonLength(6);
+ vBar.setPageIncrement(hostRect.height / 2);
+ int vSelection = vBar.getSelection ();
+ if (vSelection >= vPage) {
+ if (vPage <= 0) {
+ vSelection = 0;
+ vBar.setSelection(0);
+ }
+ //tableRect.y = -vSelection;
+ tableItemRect.y = -vSelection;
+ }
+ }
+
+ gc.dispose ();
+
+ sc.tableContent.setBounds(tableRect);
+ sc.tableItemContent.setBounds(tableItemRect);
+ inLayout = false;
+ }
+
+}
--- /dev/null
+/*
+ * Emulator Manager
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JiHye Kim <jihye424.kim@samsung.com>
+ * Minkee Lee <minkee.lee@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.emulator.manager.ui.table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+
+public class TextSizeUtil {
+ static final int STRING_EXTENT = 0;
+ static final int TEXT_EXTENT = 1;
+ static final int MARKUP_EXTENT = 2;
+
+ public static final int OMITLEN = 12;
+ public static final String OMIT = "...";
+
+ public static float getCharHeight(Font font) {
+ float result;
+ FontData fontData = font.getFontData()[0];
+ result = fontData.getHeight() * 0.48f;
+
+ if ((fontData.getStyle() & SWT.BOLD)!= 0) {
+ result *= 1.45;
+ }
+ return result;
+ }
+
+ public static int textExtent(Font font, String text) {
+
+ GC gc = new GC(Display.getCurrent());
+ gc.setFont(font);
+ FontMetrics metrics = gc.getFontMetrics();
+ int width = metrics.getAverageCharWidth();
+ gc.dispose();
+ return width * text.length();
+ }
+
+ public static int stringExtend(Font font, String text) {
+ GC gc = new GC(Display.getCurrent());
+ gc.setFont(font);
+ Point p = gc.stringExtent(text);
+ gc.dispose();
+ return p.x;
+ }
+}
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+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 );
+ }
+}
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+
+public class ReadAndDispatch {
+
+ public void spinLoop( Widget widget ) {
+ spinLoop( widget, Long.MAX_VALUE - System.currentTimeMillis() );
+ }
+
+ public void spinLoop( Widget widget, long duration ) {
+ long end = System.currentTimeMillis() + duration;
+ while( !widget.isDisposed() && ( end - System.currentTimeMillis() ) > 0 ) {
+ Display display = widget.getDisplay();
+ if( !display.readAndDispatch() ) {
+ display.sleep();
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ResourceLoader {
+
+ private static final int BUFFER_SIZE = 8192;
+
+ public byte[] load( String resourcePath ) {
+ return load( resourcePath, getClass().getClassLoader() );
+ }
+
+ public byte[] load( String resourcePath, ClassLoader classLoader ) {
+ return load( verifyExistance( classLoader.getResourceAsStream( resourcePath ), resourcePath ) );
+ }
+
+ private static byte[] load( InputStream input ) {
+ try {
+ return doLoad( input );
+ } catch( IOException e ) {
+ throw new IllegalStateException( e );
+ } finally {
+ closeSilently( input );
+ }
+ }
+
+ private static byte[] doLoad( InputStream input ) throws IOException {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[ BUFFER_SIZE ];
+ int bytesRead;
+ while( ( bytesRead = input.read( buffer ) ) != -1 ) {
+ result.write( buffer, 0, bytesRead );
+ }
+ return result.toByteArray();
+ }
+
+ private static InputStream verifyExistance( InputStream inputStream , String resourcePath ) {
+ if( inputStream == null ) {
+ throw new IllegalArgumentException( "'" + resourcePath + "' does not exist." );
+ }
+ return inputStream;
+ }
+
+ private static void closeSilently( InputStream input ) {
+ try {
+ input.close();
+ } catch( IOException e ) {
+ throw new IllegalStateException( e );
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+
+
+public class UIThreadSynchronizer {
+
+ public void asyncExec( Widget contextWidget, Runnable runnable ) {
+ new UIThreadRunner( contextWidget ).asyncExec( runnable );
+ }
+
+ public void syncExec( Widget contextWidget, Runnable runnable ) {
+ new UIThreadRunner( contextWidget ).syncExec( runnable );
+ }
+
+ private static class UIThreadRunner {
+ private final Widget contextWidget;
+
+ UIThreadRunner( Widget contextWidget ) {
+ this.contextWidget = contextWidget;
+ }
+
+ void asyncExec( Runnable runnable ) {
+ Display display = getDisplay();
+ if( display != null ) {
+ display.asyncExec( new GuardedRunnable( contextWidget, runnable ) );
+ }
+ }
+
+ void syncExec( Runnable runnable ) {
+ Display display = getDisplay();
+ if( display != null ) {
+ display.syncExec( new GuardedRunnable( contextWidget, runnable ) );
+ }
+ }
+
+ private Display getDisplay() {
+ Display result = null;
+ if( !contextWidget.isDisposed() ) {
+ result = safeGetDisplay();
+ }
+ return result;
+ }
+
+ private Display safeGetDisplay() {
+ Display result = null;
+ try {
+ result = contextWidget.getDisplay();
+ } catch( SWTException exception ) {
+ handleSWTException( exception );
+ }
+ return result;
+ }
+
+ private static void handleSWTException( SWTException exception ) {
+ if( exception.code != SWT.ERROR_WIDGET_DISPOSED ) {
+ throw exception;
+ }
+ }
+ }
+
+ private static class GuardedRunnable implements Runnable {
+ private final Widget contextWidget;
+ private final Runnable runnable;
+
+ GuardedRunnable( Widget contextWidget, Runnable runnable ) {
+ this.contextWidget = contextWidget;
+ this.runnable = runnable;
+ }
+
+ @Override
+ public void run() {
+ if( !contextWidget.isDisposed() ) {
+ runnable.run();
+ }
+ }
+ }
+
+}
--- /dev/null
+package com.codeaffine.eclipse.swt.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+
+public class Unsafe {
+
+ private Object unsafeInstance;
+ private Method allocateInstance;
+ private Method defineClass;
+
+ public Unsafe() {
+ try {
+ unsafeInstance = getUnsafeInstance();
+ allocateInstance = getAllocateInstanceMethod();
+ defineClass = getDefineClassMethod();
+ } catch( Exception unresolvable ) {
+ throw new IllegalStateException( unresolvable );
+ }
+ }
+
+ public <T> T newInstance( Class<T> type ) {
+ try {
+ return type.cast( allocateInstance.invoke( unsafeInstance, type ) );
+ } catch( IllegalAccessException iae ) {
+ throw new RuntimeException( iae );
+ } catch( InvocationTargetException ite ) {
+ throw toRuntimeException( ite );
+ }
+ }
+
+ public Class<?> defineClass(
+ String name, byte[] bytes, int offset, int length, ClassLoader loader, ProtectionDomain domain )
+ {
+ Class<?> result = loadFromClassLoader( name, loader );
+ if( result == null ) {
+ result = defineClassUnsafe( name, bytes, offset, length, loader, domain );
+ }
+ return result;
+ }
+
+ private static Object getUnsafeInstance() throws Exception {
+ Field unsafeField = getUnsafeClass().getDeclaredField( "theUnsafe" );
+ unsafeField.setAccessible( true );
+ return unsafeField.get( null );
+ }
+
+ private static Method getAllocateInstanceMethod() throws Exception {
+ return getUnsafeClass().getMethod( "allocateInstance", Class.class );
+ }
+
+ private static Method getDefineClassMethod() throws Exception {
+ return getUnsafeClass().getMethod(
+ "defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class );
+ }
+
+ private static Class<?> getUnsafeClass() throws ClassNotFoundException {
+ return Unsafe.class.getClassLoader().loadClass( "sun.misc.Unsafe" );
+ }
+
+ private static Class<?> loadFromClassLoader( String name, ClassLoader loader ) {
+ try {
+ return loader.loadClass( name );
+ } catch( SecurityException ignored ) {
+ return null;
+ } catch( ClassNotFoundException ignored ) {
+ return null;
+ }
+ }
+
+ private Class<?> defineClassUnsafe(
+ String name, byte[] bytes, int offset, int length, ClassLoader loader, ProtectionDomain domain )
+ {
+ try {
+ return ( Class<?> )defineClass.invoke(
+ unsafeInstance, name, bytes, Integer.valueOf( offset), Integer.valueOf( length ), loader, domain );
+ } catch( RuntimeException rte ) {
+ throw rte;
+ } catch( InvocationTargetException ite ) {
+ throw toRuntimeException( ite );
+ } catch( IllegalAccessException iae ) {
+ throw new RuntimeException( iae );
+ }
+ }
+
+ private static RuntimeException toRuntimeException( InvocationTargetException e ) {
+ if( e.getCause() instanceof RuntimeException ) {
+ return ( RuntimeException )e.getCause();
+ }
+ return new RuntimeException( e.getCause() );
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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;
+
+import com.codeaffine.eclipse.swt.util.ButtonClick;
+import com.codeaffine.eclipse.swt.util.MouseDownActionTimer;
+import com.codeaffine.eclipse.swt.util.MouseDownActionTimer.TimerAction;
+
+class ClickControl extends ControlAdapter implements ViewComponent, 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 ) {}
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import org.eclipse.swt.SWT;
+
+import com.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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 - 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, 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, BAR_BREADTH );
+ }
+
+ @Override
+ protected void expand( Control control, int maxEexpansion ) {
+ Rectangle bounds = control.getBounds();
+ int expand = expand( bounds.height, maxEexpansion );
+ 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 - 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( 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( 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 BAR_BREADTH = 6;
+ 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, BAR_BREADTH + maxExpansion - max( 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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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;
+
+import com.codeaffine.eclipse.swt.util.DragDetector;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import static com.codeaffine.eclipse.swt.widget.scrollbar.Direction.HORIZONTAL;
+import static com.codeaffine.eclipse.swt.widget.scrollbar.ShiftData.calculateSelectionRange;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+
+import com.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import static com.codeaffine.eclipse.swt.widget.scrollbar.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 {
+
+ 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<SelectionListener> 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<SelectionListener>();
+ 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() );
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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 {
+
+ private final int maxExpansion;
+
+ private Color background;
+ private Color foreground;
+
+ ImageDrawer( int expansion ) {
+ this.maxExpansion = expansion;
+ this.foreground = Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_DARK_SHADOW );
+ this.background = Display.getCurrent().getSystemColor( SWT.COLOR_LIST_BACKGROUND );
+ }
+
+ void setForeground( Color foreground ) {
+ if( foreground != null ) {
+ this.foreground = foreground;
+ }
+ }
+
+ Color getForeground() {
+ return foreground;
+ }
+
+ void setBackground( Color background ) {
+ if( background != null ) {
+ this.background = background;
+ }
+ }
+
+ Color getBackground() {
+ return background;
+ }
+
+ Image draw( int width, int height ) {
+ Image result = new Image( getDisplay(), width, height );
+ GC gc = new GC( result );
+ try {
+ draw( gc, width, height );
+ } finally {
+ gc.dispose();
+ }
+ return result;
+ }
+
+ 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 static Display getDisplay() {
+ return Display.getCurrent();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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;
+ }
+
+ 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.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import org.eclipse.swt.SWT;
+
+import com.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import static com.codeaffine.eclipse.swt.widget.scrollbar.Direction.HORIZONTAL;
+import static com.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Slider;
+
+// Workaround for https://github.com/rherrmann/gitplus/issues/594
+public class MouseWheelSupport {
+
+ private final FlatScrollBar scrollBar;
+
+ private Slider slider;
+ private ScrollBarAdapter scrollBarAdapter;
+
+ static class SliderAdapter extends SelectionAdapter {
+
+ private final MouseWheelSupport mouseWheelSupport;
+
+ SliderAdapter( MouseWheelSupport mouseWheelSupport ) {
+ this.mouseWheelSupport = mouseWheelSupport;
+ }
+
+ @Override
+ public void widgetSelected( SelectionEvent event ) {
+ mouseWheelSupport.updateScrollBarSelection( event.detail );
+ mouseWheelSupport.copySettings();
+ }
+ }
+
+ static class ScrollBarAdapter extends SelectionAdapter implements ControlListener, DisposeListener {
+
+ private final MouseWheelSupport mouseWheelSupport;
+
+ ScrollBarAdapter( MouseWheelSupport mouseWheelSupport ) {
+ this.mouseWheelSupport = mouseWheelSupport;
+ }
+
+ @Override
+ public void controlResized( ControlEvent event ) {
+ mouseWheelSupport.copySettings();
+ }
+
+ @Override
+ public void controlMoved( ControlEvent event ) {
+ mouseWheelSupport.copySettings();
+ }
+
+ @Override
+ public void widgetSelected( SelectionEvent event ) {
+ mouseWheelSupport.copySettings();
+ }
+ @Override
+ public void widgetDisposed( DisposeEvent event ) {
+ mouseWheelSupport.dispose();
+ }
+ }
+
+ public MouseWheelSupport( FlatScrollBar scrollBar ) {
+ this.scrollBar = scrollBar;
+ }
+
+ public Control getControl() {
+ return slider;
+ }
+
+ public void dispose() {
+ if( !scrollBar.isDisposed() ) {
+ scrollBar.removeControlListener( scrollBarAdapter );
+ }
+ scrollBar.removeSelectionListener( scrollBarAdapter );
+ slider.dispose();
+ }
+
+ public void create() {
+ if( scrollBar.getDirection() == Direction.HORIZONTAL ) {
+ slider = new Slider( scrollBar.getParent(), SWT.HORIZONTAL );
+ } else {
+ slider = new Slider( scrollBar.getParent(), SWT.VERTICAL );
+ }
+ scrollBarAdapter = new ScrollBarAdapter( this );
+ scrollBar.addControlListener( scrollBarAdapter );
+ scrollBar.addDisposeListener( scrollBarAdapter );
+ scrollBar.addSelectionListener( scrollBarAdapter );
+ slider.addSelectionListener( new SliderAdapter( this ) );
+ copySettings();
+ }
+
+ protected void copySettings() {
+ if( slider.getLayoutData() == null ) {
+ slider.setBounds( scrollBar.getBounds() );
+ }
+ slider.moveBelow( null );
+ slider.setMinimum( scrollBar.getMinimum() );
+ slider.setMaximum( scrollBar.getMaximum() );
+ slider.setThumb( scrollBar.getThumb() );
+ slider.setIncrement( scrollBar.getIncrement() );
+ slider.setPageIncrement( scrollBar.getPageIncrement() );
+ slider.setSelection( scrollBar.getSelection() );
+ }
+
+ protected void updateScrollBarSelection( int detail ) {
+ scrollBar.setSelectionInternal( slider.getSelection(), detail );
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import static java.lang.Math.abs;
+
+public class SelectionRaster {
+
+ private final FlatScrollBar scrollBar;
+ private final int rasterSize;
+
+ public SelectionRaster( FlatScrollBar scrollBar, int rasterSize ) {
+ this.scrollBar = scrollBar;
+ this.rasterSize = rasterSize;
+ }
+
+ public void updateSelection( int selection ) {
+ int rasterValue = calculateRasterValue( selection );
+ int scrollBarSelection = scrollBar.getSelection();
+ if( isDifferentRasterSection( rasterValue, scrollBarSelection ) ) {
+ scrollBar.setSelection( rasterValue );
+ }
+ }
+
+ public int calculateRasterValue( int selection ) {
+ return ( selection / rasterSize ) * rasterSize;
+ }
+
+ private boolean isDifferentRasterSection( int rasterValue, int scrollBarSelection ) {
+ return abs( rasterValue - scrollBarSelection ) >= rasterSize;
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import static com.codeaffine.eclipse.swt.widget.scrollbar.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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+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<SelectionListener> 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
--- /dev/null
+package com.codeaffine.eclipse.swt.widget.scrollbar;
+
+import org.eclipse.swt.widgets.Control;
+
+public interface ViewComponent {
+ Control getControl();
+}