Home » Eclipse Projects » Nebula » Re: Horisontal scrolling during column draging
Re: Horisontal scrolling during column draging [message #62923] |
Wed, 11 March 2009 11:59  |
Eclipse User |
|
|
|
Originally posted by: and_konon.mail.ru
This is a multi-part message in MIME format.
--------------030106070003020508050007
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hi!
We prepared a patch for Grid to add horizontal scrolling during column
drag-n-drop feature for the Grid. It contains following:
1. In case if scrolling is available for the table, there is possible to
scroll the Grid by DnD a column toward to edge of the Grid. If left or
right edge of a drag-and-dropped column header reaches right/left edge
of the Grid and there are a column behind a visible area, than next/prev
column will be shown
2. Scrolling velocity is calculated depends on distance from the reached
edge: if the distance greater VELOCITY_BORDER constant, than scrolling
delay will be less (equals to SCROLL_DELAY /VELOCITY_FAST_DEVIDER)
3. User could stop DnD at any time by pressing Esc key.
Could you review and approve an attached patch? We'd appreciate you for
any remarks.
Thank you in advance.
Regards
Andrey
P.S. The message continues the thread from 14 Dec 2007 which is not
accessible now unfortunately.
--------------030106070003020508050007
Content-Type: text/plain;
name="patch.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="patch.txt"
### Eclipse Workspace Patch 1.0
#P org.eclipse.nebula.widgets.grid
Index: src/org/eclipse/nebula/widgets/grid/Grid.java
============================================================ =======
RCS file: /cvsroot/technology/org.eclipse.swt.nebula/org.eclipse.nebul a.widgets.grid/src/org/eclipse/nebula/widgets/grid/Grid.java ,v
retrieving revision 1.63
diff -u -r1.63 Grid.java
--- src/org/eclipse/nebula/widgets/grid/Grid.java 27 Feb 2008 16:42:07 -0000 1.63
+++ src/org/eclipse/nebula/widgets/grid/Grid.java 11 Mar 2009 14:40:32 -0000
@@ -400,6 +400,16 @@
private int startHeaderDragX = 0;
/**
+ * X Offset in a header (from left border to clicked point) when the user
+ * has initiated a drag. Allows calculate possition of transparent header marker if grid
+ * was scrolled.
+ */
+ private int dragColumnOffsetX;
+
+ /** separated runnable class to implement scroller */
+ private final MiColumnScroller columnScroller;
+
+ /**
* The current X position of the mouse during a header drag.
*/
private int currentHeaderDragX = 0;
@@ -738,6 +748,8 @@
cellHeaderSelectionBackground = new Color(getDisplay(),cellSel);
setDragDetect(false);
+
+ columnScroller = new McColumnScroller(this);
}
@@ -4195,7 +4207,7 @@
*
* @return the horizontal scroll selection in pixels
*/
- private int getHScrollSelectionInPixels()
+ /*private*/ int getHScrollSelectionInPixels()
{
int selection = hScroll.getSelection();
if (columnScrolling)
@@ -4254,6 +4266,10 @@
private boolean handleColumnDragging(int x)
{
+ if (columnScroller != null) {
+ columnScroller.processScroll(x, columnBeingPushed);
+ }
+
GridColumn local_dragDropBeforeColumn = null;
GridColumn local_dragDropAfterColumn = null;
@@ -4505,6 +4521,7 @@
columnBeingPushed.getHeaderRenderer().setMouseDown(false);
startHeaderDragX = x;
+ dragColumnOffsetX = startHeaderDragX - getColumnHeaderXPosition(columnBeingPushed) ;
dragDropAfterColumn = null;
dragDropBeforeColumn = null;
@@ -5461,11 +5478,15 @@
y = 0;
}
- columnBeingPushed.getHeaderRenderer()
- .setBounds(
- getColumnHeaderXPosition(columnBeingPushed)
- + (currentHeaderDragX - startHeaderDragX), y,
- columnBeingPushed.getWidth(), height);
+ int curX = currentHeaderDragX - dragColumnOffsetX;
+
+ // avoid hiding of the dragged header into invisible area
+ if (curX <= 0) {
+ curX = 0;
+ }
+ if (currentHeaderDragX + (columnBeingPushed.getWidth() - dragColumnOffsetX) > getClientArea().width) {
+ curX = getClientArea().width - (columnBeingPushed.getWidth());
+ }
columnBeingPushed.getHeaderRenderer().paint(gc, columnBeingPushed);
columnBeingPushed.getHeaderRenderer().setSelected(false);
@@ -7141,6 +7162,9 @@
newColumnFocus = focusColumn;
break;
+ case SWT.ESC :
+ cancelDraggingColumn();
+ break;
default :
break;
}
@@ -9894,6 +9918,106 @@
if (items.size() > 0)
clear(0, items.size()-1, allChildren);
}
+
+ /**
+ * Cancel dragging of a column
+ */
+ void cancelDraggingColumn() {
+ this.draggingColumn = false;
+ columnScroller.stopScrolling();
+ redraw();
+ }
+
+
+ int getDragColumnOffsetX() {
+ return dragColumnOffsetX;
+ }
+
+ /**
+ * Updates internal state of Grid of before and after column during column DnD scrolling.
+ * Main purpose of the method is updating drop marker and transparent header from scroller.
+ * @param x current cursors x coordinate
+ * FIXME [ANK] code is dublication of original Grid code from its private method <code>handleColumnDragging</code>
+ */
+ public void caclulateBeforeAndAfterColumns(final int x) {
+ GridColumn local_dragDropBeforeColumn = null;
+ GridColumn local_dragDropAfterColumn = null;
+
+ int x2 = 1;
+
+ if (rowHeaderVisible) {
+ x2 += rowHeaderWidth + 1;
+ }
+
+ x2 -= getHScrollSelectionInPixels();
+
+ int i = 0;
+ GridColumn previousVisibleCol = null;
+ boolean nextVisibleColumnIsBeforeCol = false;
+ GridColumn firstVisibleCol = null;
+ GridColumn lastVisibleCol = null;
+
+ if (x < x2) {
+ for (final Iterator columnIterator = displayOrderedColumns
+ .iterator(); columnIterator.hasNext();) {
+ final GridColumn column = (GridColumn) columnIterator.next();
+ if (!column.isVisible()) {
+ continue;
+ }
+ local_dragDropBeforeColumn = column;
+ break;
+ }
+ local_dragDropAfterColumn = null;
+ } else {
+ for (final Iterator columnIterator = displayOrderedColumns
+ .iterator(); columnIterator.hasNext();) {
+ final GridColumn column = (GridColumn) columnIterator.next();
+ if (!column.isVisible()) {
+ continue;
+ }
+
+ i++;
+
+ if (firstVisibleCol == null) {
+ firstVisibleCol = column;
+ }
+ lastVisibleCol = column;
+
+ if (nextVisibleColumnIsBeforeCol) {
+ local_dragDropBeforeColumn = column;
+ nextVisibleColumnIsBeforeCol = false;
+ }
+
+ if (x >= x2 && x <= (x2 + column.getWidth())) {
+ if (x <= (x2 + column.getWidth() / 2)) {
+ local_dragDropBeforeColumn = column;
+ local_dragDropAfterColumn = previousVisibleCol;
+ } else {
+ local_dragDropAfterColumn = column;
+
+ // the next visible column is the before col
+ nextVisibleColumnIsBeforeCol = true;
+ }
+ }
+
+ x2 += column.getWidth();
+ previousVisibleCol = column;
+ }
+
+ if (local_dragDropBeforeColumn == null) {
+ local_dragDropAfterColumn = lastVisibleCol;
+ }
+ }
+ dragDropBeforeColumn = local_dragDropBeforeColumn;
+ dragDropAfterColumn = local_dragDropAfterColumn;
+ }
+
+ /**
+ * @return List
+ */
+ public List getDisplayOrderedColumns() {
+ return displayOrderedColumns;
+ }
}
Index: src/org/eclipse/nebula/widgets/grid/MiColumnScroller.java
============================================================ =======
RCS file: src/org/eclipse/nebula/widgets/grid/MiColumnScroller.java
diff -N src/org/eclipse/nebula/widgets/grid/MiColumnScroller.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/nebula/widgets/grid/MiColumnScroller.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,19 @@
+package org.eclipse.nebula.widgets.grid;
+
+/**
+ * Helper interface to process scrolling during column DnD
+ * @author ank@maconomy.com
+ */
+public interface MiColumnScroller {
+ /**
+ * Called from mouse move listener to process scrolling, it it is necessary
+ * @param x int current mouse coordinate
+ * @param columnBeingPushed GridColumn dragged column
+ */
+ void processScroll(int x, GridColumn columnBeingPushed);
+
+ /**
+ * Stops scrolling
+ */
+ public void stopScrolling();
+}
Index: src/org/eclipse/nebula/widgets/grid/McColumnScroller.java
============================================================ =======
RCS file: src/org/eclipse/nebula/widgets/grid/McColumnScroller.java
diff -N src/org/eclipse/nebula/widgets/grid/McColumnScroller.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/nebula/widgets/grid/McColumnScroller.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,242 @@
+package org.eclipse.nebula.widgets.grid;
+
+import java.util.Iterator;
+
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+
+/**
+ * Helper class to process scrolling during column DnD
+ * @author ank@maconomy.com
+ */
+public class McColumnScroller implements MiColumnScroller {
+
+ /**
+ * Define distance from table border to increase scrolling velocity:
+ * the father the more faster
+ */
+ public static final int VELOCITY_BORDER = 100;
+
+ /**
+ * Delay for column by column scrolling in ms
+ */
+ public static final int SCROLL_DELAY = 500;
+
+ private static final int VELOCITY_SLOW_DEVIDER = 1;
+
+ private static final int VELOCITY_FAST_DEVIDER = 4;
+
+ private final Grid grid;
+
+ private boolean scrollTable = false;
+
+ private ColumnScroller scroller;
+
+ private int x;
+
+ /**
+ * COnstructor takes related Grid as parameter
+ * @param grid
+ */
+ public McColumnScroller(Grid grid) {
+ super();
+ this.grid = grid;
+ }
+
+ /**
+ * Called from mouse move listener to process scrolling, it it is necessary
+ * @param x int current mouse coordinate
+ * @param columnBeingPushed GridColumn dragged column
+ */
+ public void processScroll(int x, GridColumn columnBeingPushed) {
+ final int colWidth = columnBeingPushed.getWidth();
+ if (isCursorOurOfArea(x, colWidth)) {
+ if (!scrollTable) {
+ scrollTable = true;
+ scrollTable(x, colWidth);
+ } else {
+ final int scrollingVelocity = calculateScrollingVelocity(x, colWidth);
+ scroller.setScrollingVelocity(scrollingVelocity);
+ }
+ } else {
+ scrollTable = false;
+ }
+ }
+
+ /**
+ * Task which makes scrolling
+ */
+ private class ColumnScroller implements Runnable {
+ private int scrollingVelocity;
+
+ /**
+ * Main constructor. Defines current velocity of scrolling and add listeners.
+ */
+ public ColumnScroller() {
+ //this.scrollingVelocity = scrollingVelocity;
+ grid.addMouseListener(new MouseListener() {
+
+ public void mouseDoubleClick(MouseEvent e) {
+ // do nothing
+ }
+
+ public void mouseDown(MouseEvent e) {
+ // do nothing
+ }
+
+ public void mouseUp(MouseEvent e) {
+ scrollTable = false;
+ }
+ });
+ grid.addFocusListener(new FocusListener() {
+
+ public void focusGained(FocusEvent e) {
+ scrollTable = false;
+ }
+
+ public void focusLost(FocusEvent e) {
+ scrollTable = false;
+ }
+ });
+ }
+
+ /**
+ * Calculates current scroll velocity and provess scrolling
+ */
+ public void run() {
+ GridColumn col;
+ int delay;
+ if (scrollingVelocity >= 0) {
+ col = findNextColumnForScrolling();
+ delay = scrollingVelocity;
+ } else {
+ col = findPrevColumnForScrolling();
+ delay = - scrollingVelocity;
+ }
+ if (col != null) {
+ grid.showColumn(col);
+ grid.caclulateBeforeAndAfterColumns(x);
+
+ }
+ if (scrollTable && delay !=0 ) {
+ grid.getDisplay().timerExec(SCROLL_DELAY/delay, this);
+ }
+ }
+
+ private GridColumn findNextColumnForScrolling() {
+ int x2 = 0;
+ if (grid.isRowHeaderVisible()) {
+ x2 += grid.getItemHeaderWidth() + 1;
+ }
+ x2 -= grid.getHScrollSelectionInPixels();
+ GridColumn lastVisibleCol = null;
+ final Iterator columnIterator = grid.getDisplayOrderedColumns().iterator();
+ GridColumn curColumn = null;
+ GridColumn prevColumn = null;
+ while (columnIterator.hasNext()) {
+ curColumn = (GridColumn) columnIterator.next();
+
+ if (!curColumn.isVisible()) {
+ continue;
+ }
+
+ if (x2 > grid.getClientArea().width) {
+ lastVisibleCol = prevColumn;
+ break;
+ }
+ x2 += curColumn.getWidth();
+ prevColumn = curColumn;
+ }
+ if (lastVisibleCol == null) {
+ lastVisibleCol = curColumn;
+ }
+ return lastVisibleCol;
+ }
+
+ private GridColumn findPrevColumnForScrolling() {
+ int x2 = 1;
+ if (grid.isRowHeaderVisible()) {
+ x2 += grid.getItemHeaderWidth();
+ }
+ x2 -= grid.getHScrollSelectionInPixels();
+ GridColumn lastVisibleCol = null;
+ final Iterator columnIterator = grid.getDisplayOrderedColumns().iterator();
+ GridColumn curColumn = null;
+ GridColumn prevColumn = null;
+ while (columnIterator.hasNext()) {
+ curColumn = (GridColumn) columnIterator.next();
+
+ if (!curColumn.isVisible()) {
+ continue;
+ }
+
+ if (x2 > 0) {
+ lastVisibleCol = prevColumn;
+ break;
+ }
+ x2 += curColumn.getWidth();
+ prevColumn = curColumn;
+ }
+ return lastVisibleCol;
+ }
+
+ /**
+ * Change current velocity of scrolling
+ * @param scrollingVelocity
+ */
+ void setScrollingVelocity(int scrollingVelocity) {
+ this.scrollingVelocity = scrollingVelocity;
+ }
+
+ }
+
+ private int calculateScrollingVelocity(final int cursorPositionX, final int colWidth) {
+ x = cursorPositionX;
+ int velocity = 0;
+
+ if (grid.getItemHeaderWidth() > cursorPositionX - grid.getDragColumnOffsetX()) {
+ if (cursorPositionX - grid.getDragColumnOffsetX() > -VELOCITY_BORDER) {
+ velocity = -VELOCITY_SLOW_DEVIDER;
+ } else {
+ velocity = -VELOCITY_FAST_DEVIDER;
+ }
+ } else if (grid.getClientArea().width < cursorPositionX + (colWidth - grid.getDragColumnOffsetX())) {
+ if (cursorPositionX - (grid.getClientArea().width) < VELOCITY_BORDER) {
+ velocity = VELOCITY_SLOW_DEVIDER;
+ } else {
+ velocity = VELOCITY_FAST_DEVIDER;
+ }
+ }
+ return velocity;
+ }
+
+ private boolean isCursorOurOfArea(final int cursorPositionX, final int draggedColumnWidth) {
+ int x = cursorPositionX;
+ if (grid.isRowHeaderVisible()) {
+ x -= grid.getItemHeaderWidth();
+ }
+ return (0 > x - grid.getDragColumnOffsetX() ) || (cursorPositionX + (draggedColumnWidth - grid.getDragColumnOffsetX()) > grid.getClientArea().width);
+ }
+
+ private void scrollTable(final int cursorPositionX, final int colWidth) {
+ final int scrollingVelocity = calculateScrollingVelocity(cursorPositionX,
+ colWidth);
+ if (scroller == null) {
+ scroller = new ColumnScroller();
+ }
+ scroller.setScrollingVelocity(scrollingVelocity);
+ grid.getDisplay().timerExec(0, scroller);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stopScrolling() {
+ scrollTable = false;
+ grid.getDisplay().timerExec(-1, scroller);
+ }
+
+}
--------------030106070003020508050007--
|
|
|
Re: Horisontal scrolling during column draging [message #62925 is a reply to message #62923] |
Wed, 11 March 2009 14:31  |
Eclipse User |
|
|
|
Hi Andrey,
This looks good. Could you by chance do 2 things:
a) File a bug
b) CC me on the bug
c) Rebase your patch on the header_footer branch
I'll take a look at the patch then and give you feedback and because of
its size we need to file a CQ.
Thanks
Tom
Andrey Kononenko schrieb:
> Hi!
>
> We prepared a patch for Grid to add horizontal scrolling during column
> drag-n-drop feature for the Grid. It contains following:
>
> 1. In case if scrolling is available for the table, there is possible to
> scroll the Grid by DnD a column toward to edge of the Grid. If left or
> right edge of a drag-and-dropped column header reaches right/left edge
> of the Grid and there are a column behind a visible area, than next/prev
> column will be shown
>
> 2. Scrolling velocity is calculated depends on distance from the reached
> edge: if the distance greater VELOCITY_BORDER constant, than scrolling
> delay will be less (equals to SCROLL_DELAY /VELOCITY_FAST_DEVIDER)
>
> 3. User could stop DnD at any time by pressing Esc key.
>
> Could you review and approve an attached patch? We'd appreciate you for
> any remarks.
>
> Thank you in advance.
>
> Regards
> Andrey
>
> P.S. The message continues the thread from 14 Dec 2007 which is not
> accessible now unfortunately.
>
|
|
|
Re: Horisontal scrolling during column draging [message #593970 is a reply to message #62923] |
Wed, 11 March 2009 14:31  |
Eclipse User |
|
|
|
Hi Andrey,
This looks good. Could you by chance do 2 things:
a) File a bug
b) CC me on the bug
c) Rebase your patch on the header_footer branch
I'll take a look at the patch then and give you feedback and because of
its size we need to file a CQ.
Thanks
Tom
Andrey Kononenko schrieb:
> Hi!
>
> We prepared a patch for Grid to add horizontal scrolling during column
> drag-n-drop feature for the Grid. It contains following:
>
> 1. In case if scrolling is available for the table, there is possible to
> scroll the Grid by DnD a column toward to edge of the Grid. If left or
> right edge of a drag-and-dropped column header reaches right/left edge
> of the Grid and there are a column behind a visible area, than next/prev
> column will be shown
>
> 2. Scrolling velocity is calculated depends on distance from the reached
> edge: if the distance greater VELOCITY_BORDER constant, than scrolling
> delay will be less (equals to SCROLL_DELAY /VELOCITY_FAST_DEVIDER)
>
> 3. User could stop DnD at any time by pressing Esc key.
>
> Could you review and approve an attached patch? We'd appreciate you for
> any remarks.
>
> Thank you in advance.
>
> Regards
> Andrey
>
> P.S. The message continues the thread from 14 Dec 2007 which is not
> accessible now unfortunately.
>
|
|
|
Goto Forum:
Current Time: Wed Apr 16 10:38:00 EDT 2025
Powered by FUDForum. Page generated in 0.03359 seconds
|