Skip to content

Commit

Permalink
Implement style pane for multi select
Browse files Browse the repository at this point in the history
  • Loading branch information
ObaraEmmanuel committed Aug 18, 2023
1 parent 4946780 commit f4e59cd
Show file tree
Hide file tree
Showing 15 changed files with 584 additions and 672 deletions.
4 changes: 2 additions & 2 deletions hoverset/ui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2714,10 +2714,10 @@ def remove(self, node=None):
self.collapse()
self.nodes.remove(node)
node.pack_forget()
if was_expanded:
if was_expanded and len(self.nodes) > 0:
# If the parent was expanded when we began removal we expand it again
self.expand()
if len(self.nodes) == 0:
if not self.nodes:
# remove the expansion icon
self._set_expander(self.BLANK)

Expand Down
2 changes: 1 addition & 1 deletion studio/feature/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
FEATURES = (
ComponentPane,
ComponentTree,
#StylePane,
StylePane,
#EventPane,
#VariablePane,
)
Expand Down
31 changes: 11 additions & 20 deletions studio/feature/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,27 +118,18 @@ def set_pref(cls, short_path, value):
def get_instance(cls):
return cls._instance

def on_select(self, widget):
def on_widgets_change(self, widgets):
"""
Called when a widget is selected in the designer
:param widget: selected widget
:return:None
"""
pass

def on_widget_change(self, old_widget, new_widget=None):
"""
Called when a widget is fundamentally altered
:param old_widget: Altered widget
:param new_widget: The new widget taking the older widgets place
Called when the widgets in the designer are changed
:param widgets: list of widgets
:return: None
"""
pass

def on_widget_layout_change(self, widget):
def on_widgets_layout_change(self, widgets):
"""
Called when layout options of a widget are changed
:param widget: Widget with altered layout options
Called when layout options of a widgets are changed
:param widgets: Widgets with altered layout options
:return: None
"""
pass
Expand All @@ -152,21 +143,21 @@ def on_widget_add(self, widget, parent):
"""
pass

def on_widget_delete(self, widget, silently=False):
def on_widgets_delete(self, widgets, silently=False):
"""
Called when a widget is deleted from the designer
:param widget: deleted widget
Called when widgets are deleted from the designer
:param widgets: deleted widgets
:param silently: flag indicating whether the deletion should be treated implicitly
which is useful for instance when you don't want the deletion to be logged in the
undo stack
:return: None
"""
pass

def on_widget_restore(self, widget):
def on_widgets_restore(self, widgets):
"""
Called when a deleted widget is restored
:param widget: restored widget
:param widgets: widgets to be restored
:return: None
"""
pass
Expand Down
12 changes: 6 additions & 6 deletions studio/feature/component_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,15 @@ def selection(self):
def studio_selection(self):
return [i.node for i in self.studio.selection]

def on_widget_delete(self, widgets, silently=False):
def on_widgets_delete(self, widgets, silently=False):
for widget in widgets:
widget.node.remove()

def on_widget_restore(self, widgets):
def on_widgets_restore(self, widgets):
for widget in widgets:
widget.layout.node.add(widget.node)

def on_widget_layout_change(self, widgets):
def on_widgets_layout_change(self, widgets):
for widget in widgets:
node = widget.node
if widget.layout == self.studio.designer:
Expand All @@ -199,9 +199,9 @@ def on_context_close(self, context):
def on_session_clear(self):
self._tree.clear()

def on_widget_change(self, old_widget, new_widget=None):
new_widget = new_widget if new_widget else old_widget
new_widget.node.widget_modified(new_widget)
def on_widgets_change(self, widgets):
for widget in widgets:
widget.node.widget_modified(widget)

def on_search_query(self, query: str):
self._tree.search(query)
Expand Down
1 change: 1 addition & 0 deletions studio/feature/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def on_drag_end(self, event):
widget = self.event_first(event, self, Container)
if isinstance(widget, Container):
widget.add_new(self.component, *self.window.drag_window.get_center())
widget.clear_highlight()


class SelectableComponent(Component):
Expand Down
75 changes: 16 additions & 59 deletions studio/feature/design.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from studio.lib.pseudo import PseudoWidget, Container, Groups
from studio.parsers.loader import DesignBuilder, BaseStudioAdapter
from studio.ui import geometry
from studio.ui.highlight import WidgetHighlighter
from studio.ui.widgets import DesignPad, CoordinateIndicator
from studio.context import BaseContext
from studio import __version__
Expand All @@ -45,7 +44,7 @@ def _move(self, widget, bounds):
self.container.position(widget, self.container.canvas_bounds(bounds))

def add_widget(self, widget, bounds=None, **kwargs):
super(PlaceLayoutStrategy, self).add_widget(widget, bounds=None, **kwargs)
super(PlaceLayoutStrategy, self).add_widget(widget, bounds=bounds, **kwargs)
super(PlaceLayoutStrategy, self).remove_widget(widget)
if bounds is None:
x = kwargs.get("x", 10)
Expand Down Expand Up @@ -114,6 +113,7 @@ def __init__(self, master, studio):
self.studio = studio
self.name_generator = NameGenerator(self.studio.pref)
self.setup_widget()
self.designer = self
self.parent = self
self.config(**self.style.bright, takefocus=True)
self.objects = []
Expand All @@ -127,7 +127,6 @@ def __init__(self, master, studio):
self._frame.bind("<Button-1>", lambda _: self.focus_set(), '+')
self._frame.bind("<Button-1>", self.set_pos, '+')
self._frame.bind('<Motion>', self.on_motion, '+')
self._frame.bind('<KeyRelease>', self._stop_displace, '+')
self._padding = 30
self.design_path = None
self.builder = DesignBuilder(self)
Expand Down Expand Up @@ -170,8 +169,6 @@ def __init__(self, master, studio):
self._studio_bindings = []
self._move_selection = []
self._all_bound = None
self._bound_highlight = WidgetHighlighter(self, self.style)
self._container_highlight = WidgetHighlighter(self, self.style)

# These variables help in skipping of several rendering frames to reduce lag when dragging items
self._skip_var = 0
Expand Down Expand Up @@ -225,13 +222,6 @@ def _set_shortcuts(self):
actions.get('STUDIO_PASTE'),
actions.get('STUDIO_DUPLICATE'),
)
# allow control of widget position using arrow keys
# shortcut_mgr.add_shortcut(
# (lambda: self.displace('right'), KeyMap.RIGHT),
# (lambda: self.displace('left'), KeyMap.LEFT),
# (lambda: self.displace('up'), KeyMap.UP),
# (lambda: self.displace('down'), KeyMap.DOWN),
# )

def _open_default(self):
self.update_idletasks()
Expand Down Expand Up @@ -411,11 +401,9 @@ def _on_handle_inactive(self, widget, direction):
if direction == "all":
if not self.current_container:
return
self._bound_highlight.clear()
self._container_highlight.clear()
container = self.current_container
self.current_container = None
container.clear_hover()
container.clear_highlight()
objs = self.studio.selection.siblings(widget)
toplevel_warning = False
for obj in objs:
Expand All @@ -437,7 +425,7 @@ def _on_handle_inactive(self, widget, direction):
layouts_changed.append(obj)

self.create_restore(layouts_changed)
self.studio.widget_layout_changed(layouts_changed)
self.studio.widgets_layout_changed(layouts_changed)
self._skip_var = 0

def _on_handle_resize(self, widget, direction, delta):
Expand All @@ -460,7 +448,7 @@ def _on_handle_resize(self, widget, direction, delta):

# TODO handle realtime layout changes
# if obj.layout.layout_strategy.realtime_support:
# self.studio.widget_layout_changed(obj)
# self.studio.widgets_layout_changed(obj)

def _on_handle_move(self, _, delta):
dx, dy = delta
Expand All @@ -476,15 +464,13 @@ def _on_handle_move(self, _, delta):
current = self.current_container
container = self.layout_at(all_bound)
self._all_bound = all_bound
self._container_highlight.highlight(container)
# self._bound_highlight.highlight_bounds(all_bound)

if container != current and current is not None:
current.end_move()
current.clear_hover()
current.clear_highlight()

if container is not None and container != current:
container.show_hover()
container.show_highlight()
self.current_container = current = container

for w in objs:
Expand Down Expand Up @@ -517,7 +503,6 @@ def _attach(self, obj):

MenuUtils.bind_all_context(obj, lambda e: self.show_menu(e, obj), add='+')
obj.bind_all('<Motion>', self.on_motion, '+')
obj.bind_all('<KeyRelease>', self._stop_displace, '+')

if "text" in obj.keys():
obj.bind_all("<Double-Button-1>", lambda _: self._show_text_editor(obj))
Expand All @@ -539,7 +524,7 @@ def _handle_select(self, obj, event):
self._last_click_pos = event.x_root, event.y_root
if event.state & EventMask.CONTROL:
self.studio.selection.toggle(obj)
else:
elif obj not in self.studio.selection:
self.studio.selection.set(obj)

def load(self, obj_class, name, container, attributes, layout, bounds=None):
Expand Down Expand Up @@ -723,10 +708,10 @@ def _select(self, _):
return

for w in self._selected - current_selection:
w.clear_highlight()
w.clear_handle()

for w in current_selection - self._selected:
w.show_highlight()
w.show_handle()

self._selected = current_selection
self.focus_set()
Expand All @@ -735,37 +720,6 @@ def _select(self, _):
def selected(self):
return self._selected

def _stop_displace(self, _):
if self._displace_active:
# this ensures event is added to undo redo stack
self._on_release(geometry.bounds(self.current_obj))
# mark the latest action as designer displace
latest = self.studio.last_action()
if latest is not None:
latest.key = "designer_displace"
self._displace_active = False

def displace(self, side):
if not self.current_obj:
return
if time.time() - self._last_displace < .5:
self.studio.pop_last_action("designer_displace")

self._on_start()
self._displace_active = True
self._last_displace = time.time()
bounds = geometry.bounds(self.current_obj)
x1, y1, x2, y2 = bounds
if side == 'right':
bounds = x1 + 1, y1, x2 + 1, y2
elif side == 'left':
bounds = x1 - 1, y1, x2 - 1, y2
elif side == 'up':
bounds = x1, y1 - 1, x2, y2 - 1
elif side == 'down':
bounds = x1, y1 + 1, x2, y2 + 1
self._on_move(bounds)

def _on_start(self):
obj = self.current_obj
if obj is not None:
Expand All @@ -789,20 +743,23 @@ def undo(_):
widgets, prev_restore_points, containers, prev_containers):
container.remove_widget(widget)
prev_container.restore_widget(widget, prev_restore_point)
self.studio.widgets_layout_changed(widgets)

def redo(_):
for widget, cur_restore_point, container, prev_container in zip(
widgets, cur_restore_points, containers, prev_containers):
prev_container.remove_widget(widget)
container.restore_widget(widget, cur_restore_point)
self.studio.widgets_layout_changed(widgets)

self.studio.new_action(Action(undo, redo))

def _text_change(self):
self.studio.style_pane.apply_style("text", self._text_editor.get_all(), list(self.selected)[0])
self.studio.style_pane.apply_style("text", self._text_editor.get_all())

def _show_text_editor(self, widget):
assert widget in self.selected
if any("text" not in w.keys() for w in self.selected):
return
self._text_editor.lift(widget)
cnf = self._collect_text_config(widget)
self._text_editor.config(**cnf)
Expand Down Expand Up @@ -833,7 +790,7 @@ def _collect_text_config(self, widget):
def _text_hide(self, *_):
self._text_editor.place_forget()

def on_widget_change(self, old_widget, new_widget=None):
def on_widgets_change(self, widgets):
pass

def on_widget_add(self, widget, parent):
Expand Down
Loading

0 comments on commit f4e59cd

Please sign in to comment.