Added menu management
This commit is contained in:
@@ -7,10 +7,12 @@ from fasthtml.components import Div
|
||||
from fasthtml.xtend import Script
|
||||
|
||||
from myfasthtml.controls.BaseCommands import BaseCommands
|
||||
from myfasthtml.controls.Menu import Menu, MenuConf
|
||||
from myfasthtml.controls.Query import Query, QueryConf
|
||||
from myfasthtml.core.commands import Command
|
||||
from myfasthtml.core.dbmanager import DbObject
|
||||
from myfasthtml.core.instances import MultipleInstance
|
||||
from myfasthtml.icons.fluent import arrow_reset20_regular
|
||||
|
||||
logger = logging.getLogger("HierarchicalCanvasGraph")
|
||||
|
||||
@@ -91,10 +93,11 @@ class Commands(BaseCommands):
|
||||
This command can be used to fix stuck/frozen canvas by resetting zoom/pan state.
|
||||
"""
|
||||
return Command(
|
||||
"ResetTransform",
|
||||
"ResetView",
|
||||
"Reset view transform",
|
||||
self._owner,
|
||||
self._owner.handle_reset_view
|
||||
self._owner.handle_reset_view,
|
||||
icon=arrow_reset20_regular
|
||||
).htmx(target=f"#{self._id}")
|
||||
|
||||
|
||||
@@ -136,6 +139,9 @@ class HierarchicalCanvasGraph(MultipleInstance):
|
||||
self._query.bind_command("QueryChanged", self.commands.apply_filter())
|
||||
self._query.bind_command("CancelQuery", self.commands.apply_filter())
|
||||
|
||||
# Add Menu
|
||||
self._menu = Menu(self, conf=MenuConf(["ResetView"]))
|
||||
|
||||
logger.debug(f"HierarchicalCanvasGraph created with id={self._id}, "
|
||||
f"nodes={len(conf.nodes)}, edges={len(conf.edges)}")
|
||||
|
||||
@@ -341,8 +347,11 @@ class HierarchicalCanvasGraph(MultipleInstance):
|
||||
options_json = json.dumps(options, indent=2)
|
||||
|
||||
return Div(
|
||||
# Query filter bar
|
||||
self._query,
|
||||
Div(
|
||||
self._query,
|
||||
self._menu,
|
||||
cls="flex justify-between m-2"
|
||||
),
|
||||
|
||||
# Canvas element (sized by JS to fill container)
|
||||
Div(
|
||||
|
||||
@@ -13,6 +13,7 @@ default_icons = {
|
||||
False: checkbox_unchecked20_regular,
|
||||
|
||||
"Brain": brain_circuit20_regular,
|
||||
"QuestionMark" : question20_regular,
|
||||
|
||||
# TreeView icons
|
||||
"TreeViewFolder": folder20_regular,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fasthtml.components import Div, Button
|
||||
from fasthtml.components import Div
|
||||
|
||||
from myfasthtml.controls.HierarchicalCanvasGraph import HierarchicalCanvasGraph, HierarchicalCanvasGraphConf
|
||||
from myfasthtml.controls.Panel import Panel
|
||||
from myfasthtml.controls.Properties import Properties
|
||||
from myfasthtml.controls.helpers import mk
|
||||
from myfasthtml.core.commands import Command
|
||||
from myfasthtml.core.instances import SingleInstance, UniqueInstance, MultipleInstance, InstancesManager
|
||||
|
||||
@@ -43,20 +42,12 @@ class InstancesDebugger(SingleInstance):
|
||||
}
|
||||
)
|
||||
self._canvas_graph = HierarchicalCanvasGraph(self, conf=graph_conf, _id="-canvas-graph")
|
||||
|
||||
# Debug button to reset transform
|
||||
reset_btn = mk.button(
|
||||
"🔄 Reset View",
|
||||
command=self._canvas_graph.commands.reset_view(),
|
||||
cls="btn btn-sm btn-ghost"
|
||||
)
|
||||
|
||||
|
||||
main_content = Div(
|
||||
Div(reset_btn, cls="p-2 flex justify-end bg-base-200"),
|
||||
self._canvas_graph,
|
||||
cls="flex flex-col h-full"
|
||||
)
|
||||
|
||||
|
||||
return self._panel.set_main(main_content)
|
||||
|
||||
def on_select_node(self, node_id=None, label=None, kind=None, type=None):
|
||||
|
||||
65
src/myfasthtml/controls/Menu.py
Normal file
65
src/myfasthtml/controls/Menu.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
from fasthtml.components import Div
|
||||
|
||||
from myfasthtml.controls.IconsHelper import IconsHelper
|
||||
from myfasthtml.controls.helpers import mk
|
||||
from myfasthtml.core.dbmanager import DbObject
|
||||
from myfasthtml.core.instances import MultipleInstance
|
||||
|
||||
|
||||
@dataclass
|
||||
class MenuConf:
|
||||
fixed_items: list = field(default_factory=list)
|
||||
|
||||
|
||||
class MenuState(DbObject):
|
||||
def __init__(self, owner, save_state):
|
||||
with self.initializing():
|
||||
super().__init__(owner, save_state=save_state)
|
||||
self.last_used: Optional[list] = None
|
||||
|
||||
|
||||
class Menu(MultipleInstance):
|
||||
def __init__(self, parent, conf=None, save_state=True, _id=None):
|
||||
super().__init__(parent, _id=_id)
|
||||
self.conf = conf or MenuConf()
|
||||
self._state = MenuState(self, save_state=save_state)
|
||||
self.usable_commands = self._get_parent_commands()
|
||||
|
||||
def _get_parent_commands(self):
|
||||
commands_obj = self._parent.commands
|
||||
|
||||
callables = [
|
||||
name
|
||||
for name in dir(commands_obj)
|
||||
if not name.startswith("_")
|
||||
and callable(getattr(commands_obj, name))
|
||||
]
|
||||
|
||||
return {
|
||||
c.name: c for c in [getattr(commands_obj, name)() for name in callables]
|
||||
}
|
||||
|
||||
def _mk_menu(self, command_name):
|
||||
command = self.usable_commands.get(command_name)
|
||||
return mk.icon(command.icon or IconsHelper.get("QuestionMark"),
|
||||
command=command,
|
||||
tooltip=command.description)
|
||||
|
||||
def render(self):
|
||||
return Div(
|
||||
Div(
|
||||
*[self._mk_menu(command_name) for command_name in self.conf.fixed_items],
|
||||
*(
|
||||
Div("|"),
|
||||
*[self._mk_menu(command_name) for command_name in self._state.last_used[:3]]
|
||||
) if self._state.last_used else [],
|
||||
cls="flex"
|
||||
),
|
||||
id=self._id
|
||||
)
|
||||
|
||||
def __ft__(self):
|
||||
return self.render()
|
||||
Reference in New Issue
Block a user