how to get the drop target from gwt-dnd - gwt

I have a vertical panel containing two rows, say row 1 and row 2, each
row contains couple of widgets, now i need to allow the user to drag
and drop widgets between row 1 and row 2, here is what i did
_handler = new DragHandler() { .... };
_widgetDragController = new PickupDragController(boundaryPanel, false);
_widgetDragController.setBehaviorMultipleSelection(false);
_widgetDragController.addDragHandler(_handler);
then for each row, create panel to hold widgets and assign a drop controller:
VerticalPanelWithSpacer vPanel = new VerticalPanelWithSpacer();
// initialize a widget drop controller for the current column VerticalPanelDropController
widgetDropController = new VerticalPanelDropController(vPanel);
_widgetDragController.registerDropController(widgetDropController);
how can i find the drop target (namely which row) when i dnd widgets between row 1 and row 2? is there any way the _widgetDragController can tell which drop controller got involved and then i can further call getDropTarget() from the drop controller?

You could implement the functionality in VerticalPanelDropController.onDrop(DragContext), which gets called when the users drop on that drop controller. The drop controller knows the VerticalPanelWithSpacer it belongs to, and the dragContext contains information such as the x, y coordinates. You could use this information (the y coordinate & the coordinates of the widget) to calculate the row which should be added (although you might need to take scrolling etc into account, which makes it a bit more tricky). Hope that helps :-)

Related

Unmerge and Assign Values Only Vertically or Horizontally Openpyxl

Using the answer provided by aka863 here: How to split merged Excel cells with Python?
I can unmerge, fill values and copy the styling. My questions is how to make the value assigning/filling process configurable.
I want the user to be able to choose whether the values will be filled vertically/horizontally.
I have tried changing the last loop where we assign the top_left_cell_values to unmerged cells. However I couldn't find a way to make it horizontal/vertical configurable. (I'm planning to use radio buttons and tkinter for this)
Its certainly possible to have the code de-merge cells and fill cells in whichever direction, vertically or horizontally regardless of which way the merge was originally. Or not fill at all, so only the top left cell retains the 'value' of the previously merged cells, which is default on unmerge.
Changing the direction of the fill requires some change and re-calculation on the max row and column values in the iter_rows loop, but is simple enough.
However it seems in your last comment you just want to give the user the option to fill or not fill on horizontal merges. In that case you just need to ask the question, and then run the iter_rows loop only if the response is yes.
The code sample below is based on the answer referenced question.
I'm assuming only single line horizontal merges since you dont mention what if anything should be done with vertical merges in the comment.
The code does initially check and indicate the merge direction either vertically or horizontally so it can be included take some action if a merge is vertical.
On code run after displaying the range and direction of the merge, the question is asked to fill, yes or no. If yes the cells are de-merged and all cells filled with the top left cell value using the iter_rows loop. If answer no then the cells are just de-merged.
from openpyxl import load_workbook
from openpyxl.utils.cell import range_boundaries
wb = load_workbook(filename='foo.xlsx')
st = wb['Sheet1']
mcr_coord_list = [mcr.coord for mcr in st.merged_cells.ranges]
direction_dict = {'v': 'vertical', 'h': 'horizontal'}
for mcr in mcr_coord_list:
print('---------------------------------------------------\n')
merge_direction = ''
min_col, min_row, max_col, max_row = range_boundaries(mcr)
top_left_cell_value = st.cell(row=min_row, column=min_col).value
if min_col == max_col:
merge_direction = 'v'
elif min_row == max_row:
merge_direction = 'h'
print(f"The cell range {mcr} is merged {direction_dict[merge_direction]}ly with the data '{top_left_cell_value}'")
while True:
demerge_fill = input('Do you want the de-merge to fill all cells(y|n)? ')
if demerge_fill.lower() in ["y", "n"]:
break
else:
print('Invalid response')
st.unmerge_cells(mcr)
if demerge_fill == 'y':
for row in st.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
for cell in row:
cell.value = top_left_cell_value
else:
print(f"Only the top left cell {mcr.split(':')[0]} will contain the data!")
wb.save('merged_tmp.xlsx')

How do I make the matlab-uitable CellSelectionCallback respond to multiple consecutive clicks in the same cell?

--UPDATE--
I discovered that the uitable does not register a 'second click' when t.ColumnEditable = true. When this is true, MATLAB waits until you personally deselect the cell to begin registering new clicks. Hence, that entire time it expects that new clicks are edits to the cell. Turn t.ColumnEditable to false and consecutive clicks register as new actions.
--
The CellSelectionCallback only seems to register clicks in new cells. For example, the following only displays 'src' and 'event' during the first click to any particular cell:
close all;
f = figure('Position',[50,62,1340,326],'Units','pixels'); % set figures so they're stacked
f.Name = 'Debugging table';
t = uitable(f,'Units','normalized','Position',[.05,.05,.9,.9]);
t.CellSelectionCallback = #cellSelected;
t.ColumnName = {};
t.RowName = {};
t.Data = magic(10);
t.FontSize = 10;
t.FontName = 'AppleGothic';
function [src,event] = cellSelected(src,event)
src
event
end
Can anyone provide a method that branches off of something like this that would allow the code inside 'cellSelected' to run on more than one consecutive click to a single cell in the active uitable? Thanks in advance.
--UPDATE--
I discovered that the uitable does not register a 'second click' when t.ColumnEditable = true. When this is true, MATLAB waits until you personally deselect the cell to begin registering new clicks. Hence, that entire time it expects that new clicks are edits to the cell. Turn t.ColumnEditable to false and consecutive clicks register as new actions that independently trigger the cellSelected callback function.
--

pyqt how to swap text in

I have a QTable Widget of one column populated with several rows, and I would like to be able to drag and drop so i can re order them.
I am able to do setDragDropMode with Internal Move, but when i move cell (0,1) to (0,3)
the (0,3) get the text correctly, but cell (0,1) is now empty. I would like to swap the text of the cell when I drop it.
class myList(QtGui.QTableWidget):
def __init__(self,parent):
super(myList,self).__init__(parent)
# self.setAcceptDrops(True)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
You can override the dropEvent callback to alter the default action. Here is a first version that writes the value in both cells.
class TableSwitcher(QtGui.QTableWidget):
def dropEvent(self, dropEvent):
item_src = self.selectedItems()[0]
item_dest = self.itemAt(dropEvent.pos())
src_value = item_src.text()
item_src.setText(item_dest.text())
item_dest.setText(src_value)
You can also let Qt performs the default behavior (move the dragged QTableWidgetItem, and delete the one you drop on) through super call , here you face the challenge that the default action will alter the state of widgets.
class TableSwitcher(QtGui.QTableWidget):
def dropEvent(self, dropEvent):
item_src = self.selectedItems()[0]
item_dest = self.itemAt(dropEvent.pos())
src_row = item_src.row()
src_col = item_src.column()
dest_value = item_dest.text()
super(TableSwitcher,self).dropEvent(dropEvent)
self.setItem(src_row,src_col, QtGui.QTableWidgetItem(dest_value))
Here is an example code using this class.
app = QtGui.QApplication(sys.argv)
table = TableSwitcher()
n = 5
table.setRowCount(n)
table.setColumnCount(1)
table.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
for i in range(n):
table.setItem(i,0,QtGui.QTableWidgetItem(str(i)))
table.show()
app.exec_()

jquery ui sortable temporary element swapping during drag

I need to implement temporary drag replacement in a size-limited jquery ui sortable list.
I have 2 sortable lists:
A "slot" with only 1 spot to hold a single element
A "bucket" that holds several elements from which the user can pick any to fill the "slot"
The user has to drag an element from the bucket into the slot. While the user is holding the element with the mouse over the slot, if the slot is already occupied, the current slotted element should be moved into the bucket to visually make room for the dragged element. Then the user has 2 options:
If the user drops the new element: insert the new element into the slot
If the user cancels the drop: move the previously slotted element back into the slot (as it was originally)
This behaviour should repeat until the user has either cancelled the drag or dropped the element into the slot or the bucket.
To visually limit the slot to a single element, I have limited it to the exact height of a single element and setted its overflow to hidden.
Unfortunately, I have not been able to produce the effect while keeping a single element in the slot at all time.
EDIT 1: Here is an example of what I have so far
$(".slot").bind("sortchange", function (event, ui) {
var slot = $(event.target);
var bucket = $(".bucket");
// Move any element already in the slot (other than the currently
// dragged element) into the bucket
var slotElements = slot.children(".item").not(ui.item);
if (slotElements.length > 0) {
for (var idx = 0; idx < slotElements.length; idx += 1) {
var element = $(slotElements[idx]);
moveAnimate(element, bucket);
}
}
});

FormLayout, FormData and controls

can someone please explain to me how FormData on FormLayout works? I'm trying to understand the FormAttachment constructors and its parameters (numerator, offset, denominator). When do you need only one of them, two of them or all of the parameters... Also, if i have a group (or a composite) which will add widgets like buttons and labels which will need to be resized as per resolution using FormData, does the Group need to have a FormLayout also? I tried specifying a width of a group with form layout but no change
FormAttachment has several different constructors, I generally use two typically:
new FormAttachment (int numerator, int offset) - If there's only two integer parameters then the first parameter represents the percentage from the edge of the parent. Which edge is determined by which slot in the FormData object you insert the FormAttachment into: FormData.top, data.bottom, data.left, and FormData.right.
new FormAttachment (Control control, int offset) - Instead of positioning the object against the parent, this positions the object next to another child object. This works in conjunction with the previous constructor so that you effectively "anchor" one element against the parent, then build your layout by positioning other elements relative to the anchor. This also allows you to easily move and insert elements into the overall layout without having to rebuild the entire layout.
The others are variations on the themes of these two. FormAttachment (int numerator, int denominator, int offset) is the same as the FormAttachment with two integer parameters, but with two the denominator just becomes "100", i.e. it turns the numerator into a percentage. But you could say something like (1, 2, 0) for 1/2 of the way across or (1, 3, 0) for 1/3 of the space.
I'm not sure what you mean about whether the Group will need to have a layout defined but in general every parent Composite must have a layout defined on it to display children elements. If you want elements to resize as the parent resizes, one option is to attach the child to both the left and right sides of the element:
FormData formData = new FormData();
formData.left = new FormAttachment (0, 0); // Attach at the 0% left with 0 offset
formData.right = new FormAttachment (100, 0); // Attach at the 100% right with 0 offset
The Eclipse site has a lot of good snippets showing FormLayout, check out:
http://www.eclipse.org/swt/snippets/
Scroll down to the FormLayout section.