changeset 196:c2639c9f86ea

Browser Side: Widgets can now be moved, header (title bar) is draggable: - DragLabel moved to tools - new LiberviaDragWidget which manage currently dragged widget - getLiberviaWidgetsCount give number of widget of WidgetsPanel - LiberviaWidget's header has now its own class - new "WIDGET" drag type /!\ not fully finished, can crash if moved on the bad border (like last row border if the widget is the only one on this row)
author Goffi <goffi@goffi.org>
date Tue, 05 Mar 2013 01:20:59 +0100
parents dd27072d8ae0
children 0fc32122a877
files browser_side/base_widget.py browser_side/contact.py browser_side/tools.py
diffstat 3 files changed, 82 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/base_widget.py	Mon Mar 04 23:01:57 2013 +0100
+++ b/browser_side/base_widget.py	Tue Mar 05 01:20:59 2013 +0100
@@ -36,6 +36,7 @@
 from pyjamas.ui import HasAlignment
 from pyjamas import DOM
 import dialog
+from tools import LiberviaDragWidget
 from pyjamas import Window
 from __pyjamas__ import doc
 
@@ -53,6 +54,8 @@
         DropCell.drop_keys[key] = callback
     
     def onDragEnter(self, event):
+        if self == LiberviaDragWidget.current:
+            return
         self.addStyleName('dragover')
         DOM.eventPreventDefault(event)
 
@@ -89,10 +92,26 @@
             item='&nbsp;'
             item_type = None
         DOM.eventPreventDefault(event)
-        if item_type in self.drop_keys:
+        if item_type == "WIDGET":
+            if not LiberviaDragWidget.current:
+                print "ERROR: No widget registered in LiberviaDragWidget !"
+                return
+            _new_panel = LiberviaDragWidget.current
+            if self == _new_panel: # We can't drop on ourself
+                return
+            # we need to remove the widget from the panel as it will be inserted elsewhere
+            widgets_panel = _new_panel.getWidgetsPanel()
+            if widgets_panel.getLiberviaWidgetsCount() == 1:
+                # the dropped widget is the only one in the panel,
+                # we don't do anything
+                self.removeStyleName('dragover')
+                return
+            widgets_panel.removeWidget(_new_panel)
+        elif item_type in self.drop_keys:
             _new_panel = self.drop_keys[item_type](self.host,item)
         else:
-            return False
+            print "WARNING: unmanaged item type"
+            return
         if isinstance(self, LiberviaWidget):
             self.host.unregisterWidget(self)
             self.onQuit()
@@ -112,6 +131,28 @@
             DOM.setStyleAttribute(td_elt, "width", "%s%%" % _width)"""
         #FIXME: delete object ? Check the right way with pyjamas
 
+class WidgetHeader(AbsolutePanel, LiberviaDragWidget):
+
+    def __init__(self, parent, title):
+        AbsolutePanel.__init__(self)
+        self.add(title)
+        button_group_wrapper = SimplePanel()
+        button_group_wrapper.setStyleName('widgetHeader_buttonsWrapper')
+        button_group = HorizontalPanel()
+        button_group.setStyleName('widgetHeader_buttonGroup')
+        setting_button = Image("media/icons/misc/settings.png")
+        setting_button.setStyleName('widgetHeader_settingButton')
+        setting_button.addClickListener(parent.onSetting)
+        close_button = Image("media/icons/misc/close.png")
+        close_button.setStyleName('widgetHeader_closeButton')
+        close_button.addClickListener(parent.onClose)
+        button_group.add(setting_button)
+        button_group.add(close_button)
+        button_group_wrapper.setWidget(button_group)
+        self.add(button_group_wrapper)
+        self.addStyleName('widgetHeader')
+        LiberviaDragWidget.__init__(self, "", "WIDGET", parent)
+
 class LiberviaWidget(DropCell, VerticalPanel, ClickHandler):
     """Libervia's widget which can replace itself with a dropped widget on DnD"""
     
@@ -127,33 +168,17 @@
         self.__title_id = HTMLPanel.createUniqueId()
         self.__setting_button_id = HTMLPanel.createUniqueId()
         self.__close_button_id = HTMLPanel.createUniqueId()
-        header = AbsolutePanel()
         self.__title = Label(title)
         self.__title.setStyleName('widgetHeader_title')
-        header.add(self.__title)
-        button_group_wrapper = SimplePanel()
-        button_group_wrapper.setStyleName('widgetHeader_buttonsWrapper')
-        button_group = HorizontalPanel()
-        button_group.setStyleName('widgetHeader_buttonGroup')
-        setting_button = Image("media/icons/misc/settings.png")
-        setting_button.setStyleName('widgetHeader_settingButton')
-        setting_button.addClickListener(self.onSetting)
-        close_button = Image("media/icons/misc/close.png")
-        close_button.setStyleName('widgetHeader_closeButton')
-        close_button.addClickListener(self.onClose)
-        button_group.add(setting_button)
-        button_group.add(close_button)
-        button_group_wrapper.setWidget(button_group)
-        header.add(button_group_wrapper)
+        header = WidgetHeader(self, self.__title)
         self.add(header)
-        header.addStyleName('widgetHeader')
         self.setSize('100%', '100%')
         self.addStyleName('widget')
         if self.__selectable:
             self.addClickListener(self)
         self.host.registerWidget(self)
 
-    def _getWidgetsPanel(self):
+    def getWidgetsPanel(self):
         current = self
         while current is not None and current.__class__ != WidgetsPanel:
             current = current.getParent()
@@ -166,7 +191,7 @@
 
     def onClose(self, sender):
         """ Called when the close button is pushed """
-        _widgetspanel = self._getWidgetsPanel()
+        _widgetspanel = self.getWidgetsPanel()
         _widgetspanel.removeWidget(self)
         self.onQuit()
 
@@ -175,7 +200,7 @@
         pass
 
     def onSetting(self, sender):
-        widpanel = self._getWidgetsPanel()
+        widpanel = self.getWidgetsPanel()
         row, col = widpanel.getIndex(self)
         body = VerticalPanel()
         
@@ -445,7 +470,7 @@
             self._sizesAdjust()
         current = self
 
-        blank_page = not [wid for wid in self.flextable if isinstance(wid, LiberviaWidget)] # do we still have widgets on the page ?
+        blank_page = self.getLiberviaWidgetsCount() == 0 # do we still have widgets on the page ?
 
         if blank_page and not self.isLocked():
             #we now notice the MainTabPanel that the WidgetsPanel is empty and need to be removed
@@ -456,6 +481,10 @@
                 current = current.getParent()
             print "Error: no MainTabPanel found !"
 
+    def getLiberviaWidgetsCount(self):
+        """ Get count of contained widgets """
+        return len([wid for wid in self.flextable if isinstance(wid, LiberviaWidget)])
+
     def getIndex(self, wid):
         return self.flextable.getIndex(wid)
 
--- a/browser_side/contact.py	Mon Mar 04 23:01:57 2013 +0100
+++ b/browser_side/contact.py	Tue Mar 05 01:20:59 2013 +0100
@@ -23,29 +23,14 @@
 from pyjamas.ui.SimplePanel import SimplePanel
 from pyjamas.ui.ScrollPanel import ScrollPanel
 from pyjamas.ui.VerticalPanel import VerticalPanel
-from pyjamas.ui.HorizontalPanel import HorizontalPanel
 from pyjamas.ui.Label import Label
 from pyjamas.ui.HTML import HTML
 from pyjamas import Window
 from pyjamas import DOM
 
-from pyjamas.ui.DragWidget import DragWidget, DragContainer
-from browser_side.tools import html_sanitize
-from jid import JID
+from browser_side.tools import DragLabel, html_sanitize
 from __pyjamas__ import doc
 
-class DragLabel(DragWidget):
-
-    def __init__(self, text, _type):
-        DragWidget.__init__(self)
-        self._text = text
-        self._type = _type
-    
-    def onDragStart(self, event):
-        dt = event.dataTransfer
-        dt.setData('text/plain', "%s\n%s" % (self._text, self._type))
-        dt.setDragImage(self.getElement(), 15, 15)
-
 class GroupLabel(DragLabel, Label):
     def __init__(self, group):
         self.group = group
--- a/browser_side/tools.py	Mon Mar 04 23:01:57 2013 +0100
+++ b/browser_side/tools.py	Tue Mar 05 01:20:59 2013 +0100
@@ -19,6 +19,35 @@
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
+from pyjamas.ui.DragWidget import DragWidget
+
 def html_sanitize(html):
     """Naive sanitization of HTML"""
     return html.replace('<','&lt;').replace('>','&gt;')
+
+class DragLabel(DragWidget):
+
+    def __init__(self, text, _type):
+        DragWidget.__init__(self)
+        self._text = text
+        self._type = _type
+    
+    def onDragStart(self, event):
+        dt = event.dataTransfer
+        dt.setData('text/plain', "%s\n%s" % (self._text, self._type))
+        dt.setDragImage(self.getElement(), 15, 15)
+
+class LiberviaDragWidget(DragLabel):
+    """ A DragLabel which keep the widget being dragged as class value """
+    current = None # widget currently dragged
+
+    def __init__(self, text, _type, widget):
+        DragLabel.__init__(self, text, _type)
+        self.widget = widget
+
+    def onDragStart(self, event):
+        LiberviaDragWidget.current = self.widget
+        DragLabel.onDragStart(self, event)
+
+    def onDragEnd(self, event):
+        LiberviaDragWidget.current = None