dhxpyt.layout

1from .layout import Layout, MainWindow
2from .layout_config import LayoutConfig, CellConfig
3
4__all__ = ["Layout", "MainWindow", "LayoutConfig", "CellConfig"]
class Layout:
 39class Layout(object, metaclass=LoadUICaller):
 40    layout_config = None
 41    def __init__(self, config: LayoutConfig = None, mainwindow=False, **kwargs):
 42        self.parent = kwargs.get("parent", None)
 43        """Initializes the layout instance."""
 44        mainconfig = self.layout_config or config or {}
 45        mainconfig = mainconfig if type(mainconfig) is dict else mainconfig.to_dict()
 46        if not mainconfig:
 47            mainconfig = LayoutConfig(
 48                css="dhx_layout-cell--bordered",
 49                type="line",
 50                rows=[
 51                    CellConfig(id="mainwindow_header", width="98vw", height="auto", header=None),
 52                    CellConfig(id="mainwindow", width="98vw", header=None)
 53                ]
 54            ).to_dict()
 55
 56        if mainwindow:
 57            self.layout = js.dhx.Layout.new("maindiv", js.JSON.parse(json.dumps(mainconfig)))
 58        else:
 59            self.layout = js.dhx.Layout.new(None, js.JSON.parse(json.dumps(mainconfig)))
 60            
 61        self.initialized = False
 62
 63    """ Placeholder Widgets Adders """
 64
 65    def load_ui(self, *args, **kwargs):
 66        """Subclass this to build your UI"""
 67        pass
 68
 69    def add_grid(self, id: str = "mainwindow", grid_config: GridConfig = None) -> Grid:
 70        """Adds a Grid widget into a Layout cell."""
 71        grid_widget = Grid(config=grid_config)
 72        self.attach(id, grid_widget.grid)
 73        if grid_config.data:
 74            grid_widget.grid.data.removeAll()
 75            grid_widget.grid.data.parse(js.JSON.parse(json.dumps(grid_config.data)))
 76        return grid_widget
 77
 78    # Define a function to wait for the element to be ready
 79    def wait_for_element(self, selector, callback):
 80        def check_element():
 81            if js.document.querySelector(selector):
 82                callback()
 83            else:
 84                js.window.setTimeout(create_proxy(check_element), 100)  # Check again after 100ms
 85
 86        check_element()
 87
 88    def add_kanban(self, id: str = "mainwindow", kanban_config: KanbanConfig = None, kanban_callback: callable = None) -> None:
 89        self.kanban_callback = kanban_callback
 90        self.kanban_config = kanban_config
 91        self.kanban_div_id = "kanban_root_" + str(uuid4()).replace("-", "") #"kanban_root"
 92        self.attach_html(id, f'<div id="{self.kanban_div_id}" style="width:100%;height:100%;"></div>')
 93        self.wait_for_element(f"#{self.kanban_div_id}", self.create_kanban)
 94
 95    def create_kanban(self):
 96        return_kanban = Kanban(self.kanban_config, f"#{self.kanban_div_id}")
 97        current_theme = js.document.documentElement.getAttribute('data-dhx-theme')
 98        if current_theme == "dark":
 99            theme = "willow-dark"
100        else:
101            theme = "willow"
102
103        return_kanban.kanban.setTheme(js.JSON.parse(json.dumps({"name": theme, "fonts": True})))
104        self.kanban_callback(return_kanban)
105    
106    def add_layout(self, id: str = "mainwindow", layout_config: LayoutConfig = None) -> TLayout:
107        """ Adds a Layout into a Layout cell """
108        layout_widget = Layout(config=layout_config)
109        self.attach(id, layout_widget.layout)
110        return layout_widget
111    
112    def add_menu(self, id: str = "mainwindow_header", menu_config: MenuConfig = None) -> Menu:
113        """ Adds a Layout into a Layout cell """
114        menu_widget = Menu(config=menu_config)
115        self.attach(id, menu_widget.menu)
116        return menu_widget
117
118    def add_toolbar(self, id: str = "mainwindow", toolbar_config: ToolbarConfig = None) -> Toolbar:
119        """Adds a Toolbar widget into a Layout cell."""
120        toolbar_widget = Toolbar(config=toolbar_config)
121        self.attach(id, toolbar_widget.toolbar)
122        return toolbar_widget
123
124    def add_sidebar(self, id: str, sidebar_config: SidebarConfig = None) -> Sidebar:
125        """Adds a Sidebar widget into a Layout cell."""
126        sidebar_widget = Sidebar(config=sidebar_config)
127        self.attach(id, sidebar_widget.sidebar)
128        return sidebar_widget
129
130    def add_form(self, id: str, form_config: FormConfig = None) -> Form:
131        """Adds a Form widget into a Layout cell."""
132        form_widget = Form(config=form_config)
133        self.attach(id, form_widget.form)
134        return form_widget
135    
136    def add_listbox(self, id: str, listbox_config: ListboxConfig = None) -> Any:
137        """Adds a Listbox widget into a Layout cell."""
138        listbox_widget = Listbox(config=listbox_config)
139        self.attach(id, listbox_widget.listbox)
140        return listbox_widget
141    
142    def add_calendar(self, id: str, calendar_config: CalendarConfig = None) -> Any:
143        """Adds a Calendar widget into a Layout cell."""
144        calendar_widget = Calendar(config=calendar_config)
145        self.attach(id, calendar_widget.calendar)
146        return calendar_widget
147    
148    def add_chart(self, id: str, chart_config: ChartConfig = None) -> Any:
149        """Adds a Chart widget into a Layout cell."""
150        chart_widget = Chart(config=chart_config)
151        self.attach(id, chart_widget.chart)
152        return chart_widget
153    
154    def add_pagination(self, id: str, pagination_config: PaginationConfig = None) -> Any:
155        """Adds a Pagination widget into a Layout cell."""
156        pagination_widget = Pagination(config=pagination_config)
157        self.attach(id, pagination_widget.pagination)
158        return pagination_widget
159    
160    def add_cardflow(self, id: str, cardflow_config: CardFlowConfig = None) -> Any:
161        """Adds a CardFlow widget into a Layout cell."""
162        cardflow_widget = CardFlow(config=cardflow_config, container=self.layout.getCell(id))
163        return cardflow_widget
164    
165    def add_ribbon(self, id: str, ribbon_config: RibbonConfig = None) -> Any:
166        """Adds a Ribbon widget into a Layout cell."""
167        ribbon_widget = Ribbon(config=ribbon_config)
168        self.attach(id, ribbon_widget.ribbon)
169        return ribbon_widget
170    
171    def add_tabbar(self, id: str, tabbar_config: TabbarConfig = None) -> Any:
172        """Adds a Tabbar widget into a Layout cell."""
173        tabbar_widget = Tabbar(config=tabbar_config)
174        self.attach(id, tabbar_widget.tabbar)
175        return tabbar_widget
176    
177    def add_timepicker(self, id: str, timepicker_config: TimepickerConfig = None) -> Any:
178        """Adds a Timepicker widget into a Layout cell."""
179        timepicker_widget = Timepicker(config=timepicker_config)
180        self.attach(id, timepicker_widget.timepicker)
181        return timepicker_widget
182    
183    def add_tree(self, id: str, tree_config: TreeConfig = None) -> Any:
184        """Adds a Tree widget into a Layout cell."""
185        tree_widget = Tree(config=tree_config)
186        self.attach(id, tree_widget.tree)
187        return tree_widget
188        
189    """ Layout API Functions """
190
191    def destructor(self) -> None:
192        """Destroys the layout instance."""
193        self.layout.destructor()
194
195    def for_each(self, callback: Callable[[Any, int, List[Any]], Any], parent_id: str = None, level: int = None) -> None:
196        """Iterates over layout cells, applying the callback function to each."""
197        proxy_callback = create_proxy(callback)
198        self.layout.forEach(proxy_callback, parent_id, level)
199
200    def get_cell(self, id: str) -> Any:
201        """Retrieves a specific layout cell by its ID."""
202        return self.layout.getCell(id)
203
204    def progress_hide(self) -> None:
205        """Hides the loading progress bar in the layout."""
206        self.layout.progressHide()
207
208    def progress_show(self) -> None:
209        """Displays the loading progress bar in the layout."""
210        self.layout.progressShow()
211
212    def remove_cell(self, id: str) -> None:
213        """Removes a specific layout cell by ID."""
214        self.layout.removeCell(id)
215
216    def resize(self, id: str) -> None:
217        """Manually triggers a resize on a cell."""
218        self.layout.resize(id)
219
220    """ Layout API Events """
221
222    def add_event_handler(self, event_name: str, handler: Callable) -> None:
223        """Helper to add event handlers dynamically."""
224        event_proxy = create_proxy(handler)
225        self.layout.events[event_name] = event_proxy
226
227    def after_add(self, handler: Callable) -> None:
228        """Fires after a cell is added."""
229        self.add_event_handler('afterAdd', handler)
230
231    def after_collapse(self, handler: Callable) -> None:
232        """Fires after a cell is collapsed."""
233        self.add_event_handler('afterCollapse', handler)
234
235    def after_expand(self, handler: Callable) -> None:
236        """Fires after a cell is expanded."""
237        self.add_event_handler('afterExpand', handler)
238
239    def after_hide(self, handler: Callable) -> None:
240        """Fires after a cell is hidden."""
241        self.add_event_handler('afterHide', handler)
242
243    def after_remove(self, handler: Callable) -> None:
244        """Fires after a cell is removed."""
245        self.add_event_handler('afterRemove', handler)
246
247    def after_resize_end(self, handler: Callable) -> None:
248        """Fires after a cell resize ends."""
249        self.add_event_handler('afterResizeEnd', handler)
250
251    def after_show(self, handler: Callable) -> None:
252        """Fires after a cell is shown."""
253        self.add_event_handler('afterShow', handler)
254
255    def before_add(self, handler: Callable) -> None:
256        """Fires before adding a cell, returns false to prevent."""
257        self.add_event_handler('beforeAdd', handler)
258
259    def before_collapse(self, handler: Callable) -> None:
260        """Fires before collapsing a cell, returns false to prevent."""
261        self.add_event_handler('beforeCollapse', handler)
262
263    def before_expand(self, handler: Callable) -> None:
264        """Fires before expanding a cell, returns false to prevent."""
265        self.add_event_handler('beforeExpand', handler)
266
267    def before_hide(self, handler: Callable) -> None:
268        """Fires before hiding a cell, returns false to prevent."""
269        self.add_event_handler('beforeHide', handler)
270
271    def before_remove(self, handler: Callable) -> None:
272        """Fires before removing a cell, returns false to prevent."""
273        self.add_event_handler('beforeRemove', handler)
274
275    def before_resize_start(self, handler: Callable) -> None:
276        """Fires before resizing a cell, returns false to prevent."""
277        self.add_event_handler('beforeResizeStart', handler)
278
279    def before_show(self, handler: Callable) -> None:
280        """Fires before showing a cell, returns false to prevent."""
281        self.add_event_handler('beforeShow', handler)
282
283    """ Layout API Properties """
284
285    @property
286    def cols(self) -> List[Dict[Any, Any]]:
287        """Gets or sets the columns of the layout."""
288        return self.layout.cols
289
290    @cols.setter
291    def cols(self, value: List[Dict[Any, Any]]) -> None:
292        self.layout.cols = value
293
294    @property
295    def css(self) -> str:
296        """Gets or sets the CSS class for the layout."""
297        return self.layout.css
298
299    @css.setter
300    def css(self, value: str) -> None:
301        self.layout.css = value
302
303    @property
304    def rows(self) -> List[Dict[Any, Any]]:
305        """Gets or sets the rows of the layout."""
306        return self.layout.rows
307
308    @rows.setter
309    def rows(self, value: List[Dict[Any, Any]]) -> None:
310        self.layout.rows = value
311
312    @property
313    def type(self) -> str:
314        """Gets or sets the layout type ('line', 'wide', 'space', 'none')."""
315        return self.layout.type
316
317    @type.setter
318    def type(self, value: str) -> None:
319        self.layout.type = value
320
321    """ Cell API Functions """
322
323    def attach(self, id: str, component: Union[str, Any], config: Dict[str, Any] = None) -> Any:
324        """Attaches a component or HTML content to a cell."""
325        return self.layout.getCell(id).attach(component, js.JSON.parse(json.dumps(config or {})))
326
327    def attach_html(self, id: str, html: str) -> None:
328        """Inserts HTML content into a cell."""
329        self.layout.getCell(id).attachHTML(html)
330
331    def collapse(self, id: str) -> None:
332        """Collapses the specified cell."""
333        self.layout.getCell(id).collapse()
334
335    def detach(self, id: str) -> None:
336        """Removes an attached component or content from a cell."""
337        self.layout.getCell(id).detach()
338
339    def expand(self, id: str) -> None:
340        """Expands the collapsed cell."""
341        self.layout.getCell(id).expand()
342
343    def get_parent(self, id: str) -> Any:
344        """Returns the parent cell of the current cell."""
345        return self.layout.getCell(id).getParent()
346
347    def get_widget(self, id: str) -> Any:
348        """Returns the attached widget in the layout cell."""
349        return self.layout.getCell(id).getWidget()
350
351    def hide(self, id: str) -> None:
352        """Hides the specified cell."""
353        self.layout.getCell(id).hide()
354
355    def is_visible(self, id: str) -> bool:
356        """Checks if the cell is visible."""
357        return self.layout.getCell(id).isVisible()
358
359    def paint(self) -> None:
360        """Repaints the layout."""
361        self.layout.paint()
362
363    def toggle(self, id: str) -> None:
364        """Toggles between collapsing and expanding the cell."""
365        self.layout.getCell(id).toggle()
366
367    """ Cell API Properties """
368
369    @property
370    def align(self) -> str:
371        """Gets or sets the alignment of the content inside a cell."""
372        return self.layout.align
373
374    @align.setter
375    def align(self, value: str) -> None:
376        self.layout.align = value
377
378    @property
379    def resizable(self) -> bool:
380        """Gets or sets whether the cell can be resized."""
381        return self.layout.resizable
382
383    @resizable.setter
384    def resizable(self, value: bool) -> None:
385        self.layout.resizable = value
386
387    # Add other properties similarly...
Layout(*args, **kwargs)
33    def __call__(cls, *args, **kwargs):
34        """Called when you call MyNewClass() """
35        obj = type.__call__(cls, *args, **kwargs)
36        obj.load_ui()
37        return obj

Called when you call MyNewClass()

layout_config = None
parent

Initializes the layout instance.

initialized

Placeholder Widgets Adders

def load_ui(self, *args, **kwargs):
65    def load_ui(self, *args, **kwargs):
66        """Subclass this to build your UI"""
67        pass

Subclass this to build your UI

def add_grid( self, id: str = 'mainwindow', grid_config: dhxpyt.grid.GridConfig = None) -> dhxpyt.grid.Grid:
69    def add_grid(self, id: str = "mainwindow", grid_config: GridConfig = None) -> Grid:
70        """Adds a Grid widget into a Layout cell."""
71        grid_widget = Grid(config=grid_config)
72        self.attach(id, grid_widget.grid)
73        if grid_config.data:
74            grid_widget.grid.data.removeAll()
75            grid_widget.grid.data.parse(js.JSON.parse(json.dumps(grid_config.data)))
76        return grid_widget

Adds a Grid widget into a Layout cell.

def wait_for_element(self, selector, callback):
79    def wait_for_element(self, selector, callback):
80        def check_element():
81            if js.document.querySelector(selector):
82                callback()
83            else:
84                js.window.setTimeout(create_proxy(check_element), 100)  # Check again after 100ms
85
86        check_element()
def add_kanban( self, id: str = 'mainwindow', kanban_config: dhxpyt.kanban.KanbanConfig = None, kanban_callback: <built-in function callable> = None) -> None:
88    def add_kanban(self, id: str = "mainwindow", kanban_config: KanbanConfig = None, kanban_callback: callable = None) -> None:
89        self.kanban_callback = kanban_callback
90        self.kanban_config = kanban_config
91        self.kanban_div_id = "kanban_root_" + str(uuid4()).replace("-", "") #"kanban_root"
92        self.attach_html(id, f'<div id="{self.kanban_div_id}" style="width:100%;height:100%;"></div>')
93        self.wait_for_element(f"#{self.kanban_div_id}", self.create_kanban)
def create_kanban(self):
 95    def create_kanban(self):
 96        return_kanban = Kanban(self.kanban_config, f"#{self.kanban_div_id}")
 97        current_theme = js.document.documentElement.getAttribute('data-dhx-theme')
 98        if current_theme == "dark":
 99            theme = "willow-dark"
100        else:
101            theme = "willow"
102
103        return_kanban.kanban.setTheme(js.JSON.parse(json.dumps({"name": theme, "fonts": True})))
104        self.kanban_callback(return_kanban)
def add_layout( self, id: str = 'mainwindow', layout_config: LayoutConfig = None) -> ~TLayout:
106    def add_layout(self, id: str = "mainwindow", layout_config: LayoutConfig = None) -> TLayout:
107        """ Adds a Layout into a Layout cell """
108        layout_widget = Layout(config=layout_config)
109        self.attach(id, layout_widget.layout)
110        return layout_widget

Adds a Layout into a Layout cell

def add_menu( self, id: str = 'mainwindow_header', menu_config: dhxpyt.menu.MenuConfig = None) -> dhxpyt.menu.Menu:
112    def add_menu(self, id: str = "mainwindow_header", menu_config: MenuConfig = None) -> Menu:
113        """ Adds a Layout into a Layout cell """
114        menu_widget = Menu(config=menu_config)
115        self.attach(id, menu_widget.menu)
116        return menu_widget

Adds a Layout into a Layout cell

def add_toolbar( self, id: str = 'mainwindow', toolbar_config: dhxpyt.toolbar.ToolbarConfig = None) -> dhxpyt.toolbar.Toolbar:
118    def add_toolbar(self, id: str = "mainwindow", toolbar_config: ToolbarConfig = None) -> Toolbar:
119        """Adds a Toolbar widget into a Layout cell."""
120        toolbar_widget = Toolbar(config=toolbar_config)
121        self.attach(id, toolbar_widget.toolbar)
122        return toolbar_widget

Adds a Toolbar widget into a Layout cell.

def add_sidebar( self, id: str, sidebar_config: dhxpyt.sidebar.SidebarConfig = None) -> dhxpyt.sidebar.Sidebar:
124    def add_sidebar(self, id: str, sidebar_config: SidebarConfig = None) -> Sidebar:
125        """Adds a Sidebar widget into a Layout cell."""
126        sidebar_widget = Sidebar(config=sidebar_config)
127        self.attach(id, sidebar_widget.sidebar)
128        return sidebar_widget

Adds a Sidebar widget into a Layout cell.

def add_form( self, id: str, form_config: dhxpyt.form.FormConfig = None) -> dhxpyt.form.Form:
130    def add_form(self, id: str, form_config: FormConfig = None) -> Form:
131        """Adds a Form widget into a Layout cell."""
132        form_widget = Form(config=form_config)
133        self.attach(id, form_widget.form)
134        return form_widget

Adds a Form widget into a Layout cell.

def add_listbox( self, id: str, listbox_config: dhxpyt.listbox.ListboxConfig = None) -> Any:
136    def add_listbox(self, id: str, listbox_config: ListboxConfig = None) -> Any:
137        """Adds a Listbox widget into a Layout cell."""
138        listbox_widget = Listbox(config=listbox_config)
139        self.attach(id, listbox_widget.listbox)
140        return listbox_widget

Adds a Listbox widget into a Layout cell.

def add_calendar( self, id: str, calendar_config: dhxpyt.calendar.CalendarConfig = None) -> Any:
142    def add_calendar(self, id: str, calendar_config: CalendarConfig = None) -> Any:
143        """Adds a Calendar widget into a Layout cell."""
144        calendar_widget = Calendar(config=calendar_config)
145        self.attach(id, calendar_widget.calendar)
146        return calendar_widget

Adds a Calendar widget into a Layout cell.

def add_chart( self, id: str, chart_config: dhxpyt.chart.ChartConfig = None) -> Any:
148    def add_chart(self, id: str, chart_config: ChartConfig = None) -> Any:
149        """Adds a Chart widget into a Layout cell."""
150        chart_widget = Chart(config=chart_config)
151        self.attach(id, chart_widget.chart)
152        return chart_widget

Adds a Chart widget into a Layout cell.

def add_pagination( self, id: str, pagination_config: dhxpyt.pagination.PaginationConfig = None) -> Any:
154    def add_pagination(self, id: str, pagination_config: PaginationConfig = None) -> Any:
155        """Adds a Pagination widget into a Layout cell."""
156        pagination_widget = Pagination(config=pagination_config)
157        self.attach(id, pagination_widget.pagination)
158        return pagination_widget

Adds a Pagination widget into a Layout cell.

def add_cardflow( self, id: str, cardflow_config: dhxpyt.cardflow.CardFlowConfig = None) -> Any:
160    def add_cardflow(self, id: str, cardflow_config: CardFlowConfig = None) -> Any:
161        """Adds a CardFlow widget into a Layout cell."""
162        cardflow_widget = CardFlow(config=cardflow_config, container=self.layout.getCell(id))
163        return cardflow_widget

Adds a CardFlow widget into a Layout cell.

def add_ribbon( self, id: str, ribbon_config: dhxpyt.ribbon.RibbonConfig = None) -> Any:
165    def add_ribbon(self, id: str, ribbon_config: RibbonConfig = None) -> Any:
166        """Adds a Ribbon widget into a Layout cell."""
167        ribbon_widget = Ribbon(config=ribbon_config)
168        self.attach(id, ribbon_widget.ribbon)
169        return ribbon_widget

Adds a Ribbon widget into a Layout cell.

def add_tabbar( self, id: str, tabbar_config: dhxpyt.tabbar.TabbarConfig = None) -> Any:
171    def add_tabbar(self, id: str, tabbar_config: TabbarConfig = None) -> Any:
172        """Adds a Tabbar widget into a Layout cell."""
173        tabbar_widget = Tabbar(config=tabbar_config)
174        self.attach(id, tabbar_widget.tabbar)
175        return tabbar_widget

Adds a Tabbar widget into a Layout cell.

def add_timepicker( self, id: str, timepicker_config: dhxpyt.timepicker.TimepickerConfig = None) -> Any:
177    def add_timepicker(self, id: str, timepicker_config: TimepickerConfig = None) -> Any:
178        """Adds a Timepicker widget into a Layout cell."""
179        timepicker_widget = Timepicker(config=timepicker_config)
180        self.attach(id, timepicker_widget.timepicker)
181        return timepicker_widget

Adds a Timepicker widget into a Layout cell.

def add_tree( self, id: str, tree_config: dhxpyt.tree.TreeConfig = None) -> Any:
183    def add_tree(self, id: str, tree_config: TreeConfig = None) -> Any:
184        """Adds a Tree widget into a Layout cell."""
185        tree_widget = Tree(config=tree_config)
186        self.attach(id, tree_widget.tree)
187        return tree_widget

Adds a Tree widget into a Layout cell.

def destructor(self) -> None:
191    def destructor(self) -> None:
192        """Destroys the layout instance."""
193        self.layout.destructor()

Destroys the layout instance.

def for_each( self, callback: Callable[[Any, int, List[Any]], Any], parent_id: str = None, level: int = None) -> None:
195    def for_each(self, callback: Callable[[Any, int, List[Any]], Any], parent_id: str = None, level: int = None) -> None:
196        """Iterates over layout cells, applying the callback function to each."""
197        proxy_callback = create_proxy(callback)
198        self.layout.forEach(proxy_callback, parent_id, level)

Iterates over layout cells, applying the callback function to each.

def get_cell(self, id: str) -> Any:
200    def get_cell(self, id: str) -> Any:
201        """Retrieves a specific layout cell by its ID."""
202        return self.layout.getCell(id)

Retrieves a specific layout cell by its ID.

def progress_hide(self) -> None:
204    def progress_hide(self) -> None:
205        """Hides the loading progress bar in the layout."""
206        self.layout.progressHide()

Hides the loading progress bar in the layout.

def progress_show(self) -> None:
208    def progress_show(self) -> None:
209        """Displays the loading progress bar in the layout."""
210        self.layout.progressShow()

Displays the loading progress bar in the layout.

def remove_cell(self, id: str) -> None:
212    def remove_cell(self, id: str) -> None:
213        """Removes a specific layout cell by ID."""
214        self.layout.removeCell(id)

Removes a specific layout cell by ID.

def resize(self, id: str) -> None:
216    def resize(self, id: str) -> None:
217        """Manually triggers a resize on a cell."""
218        self.layout.resize(id)

Manually triggers a resize on a cell.

def add_event_handler(self, event_name: str, handler: Callable) -> None:
222    def add_event_handler(self, event_name: str, handler: Callable) -> None:
223        """Helper to add event handlers dynamically."""
224        event_proxy = create_proxy(handler)
225        self.layout.events[event_name] = event_proxy

Helper to add event handlers dynamically.

def after_add(self, handler: Callable) -> None:
227    def after_add(self, handler: Callable) -> None:
228        """Fires after a cell is added."""
229        self.add_event_handler('afterAdd', handler)

Fires after a cell is added.

def after_collapse(self, handler: Callable) -> None:
231    def after_collapse(self, handler: Callable) -> None:
232        """Fires after a cell is collapsed."""
233        self.add_event_handler('afterCollapse', handler)

Fires after a cell is collapsed.

def after_expand(self, handler: Callable) -> None:
235    def after_expand(self, handler: Callable) -> None:
236        """Fires after a cell is expanded."""
237        self.add_event_handler('afterExpand', handler)

Fires after a cell is expanded.

def after_hide(self, handler: Callable) -> None:
239    def after_hide(self, handler: Callable) -> None:
240        """Fires after a cell is hidden."""
241        self.add_event_handler('afterHide', handler)

Fires after a cell is hidden.

def after_remove(self, handler: Callable) -> None:
243    def after_remove(self, handler: Callable) -> None:
244        """Fires after a cell is removed."""
245        self.add_event_handler('afterRemove', handler)

Fires after a cell is removed.

def after_resize_end(self, handler: Callable) -> None:
247    def after_resize_end(self, handler: Callable) -> None:
248        """Fires after a cell resize ends."""
249        self.add_event_handler('afterResizeEnd', handler)

Fires after a cell resize ends.

def after_show(self, handler: Callable) -> None:
251    def after_show(self, handler: Callable) -> None:
252        """Fires after a cell is shown."""
253        self.add_event_handler('afterShow', handler)

Fires after a cell is shown.

def before_add(self, handler: Callable) -> None:
255    def before_add(self, handler: Callable) -> None:
256        """Fires before adding a cell, returns false to prevent."""
257        self.add_event_handler('beforeAdd', handler)

Fires before adding a cell, returns false to prevent.

def before_collapse(self, handler: Callable) -> None:
259    def before_collapse(self, handler: Callable) -> None:
260        """Fires before collapsing a cell, returns false to prevent."""
261        self.add_event_handler('beforeCollapse', handler)

Fires before collapsing a cell, returns false to prevent.

def before_expand(self, handler: Callable) -> None:
263    def before_expand(self, handler: Callable) -> None:
264        """Fires before expanding a cell, returns false to prevent."""
265        self.add_event_handler('beforeExpand', handler)

Fires before expanding a cell, returns false to prevent.

def before_hide(self, handler: Callable) -> None:
267    def before_hide(self, handler: Callable) -> None:
268        """Fires before hiding a cell, returns false to prevent."""
269        self.add_event_handler('beforeHide', handler)

Fires before hiding a cell, returns false to prevent.

def before_remove(self, handler: Callable) -> None:
271    def before_remove(self, handler: Callable) -> None:
272        """Fires before removing a cell, returns false to prevent."""
273        self.add_event_handler('beforeRemove', handler)

Fires before removing a cell, returns false to prevent.

def before_resize_start(self, handler: Callable) -> None:
275    def before_resize_start(self, handler: Callable) -> None:
276        """Fires before resizing a cell, returns false to prevent."""
277        self.add_event_handler('beforeResizeStart', handler)

Fires before resizing a cell, returns false to prevent.

def before_show(self, handler: Callable) -> None:
279    def before_show(self, handler: Callable) -> None:
280        """Fires before showing a cell, returns false to prevent."""
281        self.add_event_handler('beforeShow', handler)

Fires before showing a cell, returns false to prevent.

cols: List[Dict[Any, Any]]
285    @property
286    def cols(self) -> List[Dict[Any, Any]]:
287        """Gets or sets the columns of the layout."""
288        return self.layout.cols

Gets or sets the columns of the layout.

css: str
294    @property
295    def css(self) -> str:
296        """Gets or sets the CSS class for the layout."""
297        return self.layout.css

Gets or sets the CSS class for the layout.

rows: List[Dict[Any, Any]]
303    @property
304    def rows(self) -> List[Dict[Any, Any]]:
305        """Gets or sets the rows of the layout."""
306        return self.layout.rows

Gets or sets the rows of the layout.

type: str
312    @property
313    def type(self) -> str:
314        """Gets or sets the layout type ('line', 'wide', 'space', 'none')."""
315        return self.layout.type

Gets or sets the layout type ('line', 'wide', 'space', 'none').

def attach( self, id: str, component: Union[str, Any], config: Dict[str, Any] = None) -> Any:
323    def attach(self, id: str, component: Union[str, Any], config: Dict[str, Any] = None) -> Any:
324        """Attaches a component or HTML content to a cell."""
325        return self.layout.getCell(id).attach(component, js.JSON.parse(json.dumps(config or {})))

Attaches a component or HTML content to a cell.

def attach_html(self, id: str, html: str) -> None:
327    def attach_html(self, id: str, html: str) -> None:
328        """Inserts HTML content into a cell."""
329        self.layout.getCell(id).attachHTML(html)

Inserts HTML content into a cell.

def collapse(self, id: str) -> None:
331    def collapse(self, id: str) -> None:
332        """Collapses the specified cell."""
333        self.layout.getCell(id).collapse()

Collapses the specified cell.

def detach(self, id: str) -> None:
335    def detach(self, id: str) -> None:
336        """Removes an attached component or content from a cell."""
337        self.layout.getCell(id).detach()

Removes an attached component or content from a cell.

def expand(self, id: str) -> None:
339    def expand(self, id: str) -> None:
340        """Expands the collapsed cell."""
341        self.layout.getCell(id).expand()

Expands the collapsed cell.

def get_parent(self, id: str) -> Any:
343    def get_parent(self, id: str) -> Any:
344        """Returns the parent cell of the current cell."""
345        return self.layout.getCell(id).getParent()

Returns the parent cell of the current cell.

def get_widget(self, id: str) -> Any:
347    def get_widget(self, id: str) -> Any:
348        """Returns the attached widget in the layout cell."""
349        return self.layout.getCell(id).getWidget()

Returns the attached widget in the layout cell.

def hide(self, id: str) -> None:
351    def hide(self, id: str) -> None:
352        """Hides the specified cell."""
353        self.layout.getCell(id).hide()

Hides the specified cell.

def is_visible(self, id: str) -> bool:
355    def is_visible(self, id: str) -> bool:
356        """Checks if the cell is visible."""
357        return self.layout.getCell(id).isVisible()

Checks if the cell is visible.

def paint(self) -> None:
359    def paint(self) -> None:
360        """Repaints the layout."""
361        self.layout.paint()

Repaints the layout.

def toggle(self, id: str) -> None:
363    def toggle(self, id: str) -> None:
364        """Toggles between collapsing and expanding the cell."""
365        self.layout.getCell(id).toggle()

Toggles between collapsing and expanding the cell.

align: str
369    @property
370    def align(self) -> str:
371        """Gets or sets the alignment of the content inside a cell."""
372        return self.layout.align

Gets or sets the alignment of the content inside a cell.

resizable: bool
378    @property
379    def resizable(self) -> bool:
380        """Gets or sets whether the cell can be resized."""
381        return self.layout.resizable

Gets or sets whether the cell can be resized.

class MainWindow(dhxpyt.layout.Layout):
389class MainWindow(Layout):
390    def __init__(self) -> None:
391        """Initialize the Main Window layout."""
392        super().__init__(mainwindow=True)
393        self.initialized = True
394        self.cookie_status = None
395
396    def set_theme(self, theme: str) -> None:
397        """Sets the layout theme."""
398        js.dhx.setTheme(theme)
399
400    def show_cookie_banner(self):
401        # Suppose you've got a <div id="cookie-banner"> in your HTML
402        cookie_banner = js.document.getElementById("cookie-banner")
403        cookie_banner.style.display = "block"
404
405    def hide_cookie_banner(self):
406        cookie_banner = js.document.getElementById("cookie-banner")
407        cookie_banner.style.display = "none"
408
409    def accept_cookies(self, _event=None):
410        # Set a cookie in the browser to remember consent
411        js.document.cookie = "cookie_consent=accepted; path=/; max-age=31536000"
412        self.hide_cookie_banner()
413        self.cookie_status = True
414
415    def reject_cookies(self, _event=None):
416        # Possibly set a cookie or local storage to remember "rejected"
417        js.document.cookie = "cookie_consent=rejected; path=/; max-age=31536000"
418        self.hide_cookie_banner()
419        self.cookie_status = False
420
421    def check_cookie_consent(self):
422        # Check the document.cookie in JavaScript from Pyodide
423        cookies = js.document.cookie
424        if "cookie_consent=accepted" not in cookies and "cookie_consent=rejected" not in cookies:
425            self.show_cookie_banner()
426            accept_button = js.document.getElementById("accept-btn")
427            reject_button = js.document.getElementById("reject-btn")
428
429            accept_button.addEventListener("click", create_proxy(self.accept_cookies))
430            reject_button.addEventListener("click", create_proxy(self.reject_cookies))
MainWindow()
390    def __init__(self) -> None:
391        """Initialize the Main Window layout."""
392        super().__init__(mainwindow=True)
393        self.initialized = True
394        self.cookie_status = None

Initialize the Main Window layout.

initialized

Placeholder Widgets Adders

cookie_status
def set_theme(self, theme: str) -> None:
396    def set_theme(self, theme: str) -> None:
397        """Sets the layout theme."""
398        js.dhx.setTheme(theme)

Sets the layout theme.

def accept_cookies(self, _event=None):
409    def accept_cookies(self, _event=None):
410        # Set a cookie in the browser to remember consent
411        js.document.cookie = "cookie_consent=accepted; path=/; max-age=31536000"
412        self.hide_cookie_banner()
413        self.cookie_status = True
def reject_cookies(self, _event=None):
415    def reject_cookies(self, _event=None):
416        # Possibly set a cookie or local storage to remember "rejected"
417        js.document.cookie = "cookie_consent=rejected; path=/; max-age=31536000"
418        self.hide_cookie_banner()
419        self.cookie_status = False
class LayoutConfig:
 43class LayoutConfig:
 44    """
 45    Configuration class for Layout. Contains rows and columns with nested cells.
 46    """
 47    def __init__(self,
 48                 type: str = "line",
 49                 rows: List[List[CellConfig]] = None,
 50                 cols: List[List[CellConfig]] = None,
 51                 css: str = None):
 52        """
 53        :param type: (Optional) Type of the layout ("line", "wide", etc.)
 54        :param rows: (Optional) A list of rows, where each row is a list of CellConfig objects.
 55        :param cols: (Optional) A list of columns, where each column is a list of CellConfig objects.
 56        :param css: (Optional) CSS class to apply to the entire layout.
 57        """
 58        self.type = type
 59        self.rows = rows if rows else None
 60        self.cols = cols if cols else None
 61        self.css = css
 62
 63    def process_nested_dict(self, obj):
 64        # If obj is a dictionary, process its 'rows' and 'cols' if they exist
 65        if isinstance(obj, dict):
 66            if 'rows' in obj:
 67                obj['rows'] = [
 68                    self.process_nested_dict(cell) if isinstance(cell, (dict, object)) else cell for cell in obj['rows']
 69                ]
 70            if 'cols' in obj:
 71                obj['cols'] = [
 72                    self.process_nested_dict(cell) if isinstance(cell, (dict, object)) else cell for cell in obj['cols']
 73                ]
 74            return obj
 75        # If obj is an object, convert it to a dict using to_dict()
 76        elif hasattr(obj, 'to_dict'):
 77            return obj.to_dict()
 78        # Return obj as-is if it is not a dict or does not have to_dict()
 79        return obj
 80
 81    def to_dict(self) -> Dict[str, Any]:
 82        """
 83        Converts the LayoutConfig into a dictionary format that can be
 84        passed into the layout constructor. Handles nested rows and cols.
 85        """
 86        # Create config_dict by excluding None values
 87        config_dict = {k: v for k, v in self.__dict__.items() if v is not None}
 88
 89        # Convert rows and columns to dictionaries, ensuring nested dicts are handled
 90        if self.rows:
 91            config_dict['rows'] = [
 92                self.process_nested_dict(cell) for cell in self.rows
 93            ]
 94
 95        if self.cols:
 96            config_dict['cols'] = [
 97                self.process_nested_dict(cell) for cell in self.cols
 98        ]
 99
100        return config_dict

Configuration class for Layout. Contains rows and columns with nested cells.

LayoutConfig( type: str = 'line', rows: List[List[CellConfig]] = None, cols: List[List[CellConfig]] = None, css: str = None)
47    def __init__(self,
48                 type: str = "line",
49                 rows: List[List[CellConfig]] = None,
50                 cols: List[List[CellConfig]] = None,
51                 css: str = None):
52        """
53        :param type: (Optional) Type of the layout ("line", "wide", etc.)
54        :param rows: (Optional) A list of rows, where each row is a list of CellConfig objects.
55        :param cols: (Optional) A list of columns, where each column is a list of CellConfig objects.
56        :param css: (Optional) CSS class to apply to the entire layout.
57        """
58        self.type = type
59        self.rows = rows if rows else None
60        self.cols = cols if cols else None
61        self.css = css
Parameters
  • type: (Optional) Type of the layout ("line", "wide", etc.)
  • rows: (Optional) A list of rows, where each row is a list of CellConfig objects.
  • cols: (Optional) A list of columns, where each column is a list of CellConfig objects.
  • css: (Optional) CSS class to apply to the entire layout.
type
rows
cols
css
def process_nested_dict(self, obj):
63    def process_nested_dict(self, obj):
64        # If obj is a dictionary, process its 'rows' and 'cols' if they exist
65        if isinstance(obj, dict):
66            if 'rows' in obj:
67                obj['rows'] = [
68                    self.process_nested_dict(cell) if isinstance(cell, (dict, object)) else cell for cell in obj['rows']
69                ]
70            if 'cols' in obj:
71                obj['cols'] = [
72                    self.process_nested_dict(cell) if isinstance(cell, (dict, object)) else cell for cell in obj['cols']
73                ]
74            return obj
75        # If obj is an object, convert it to a dict using to_dict()
76        elif hasattr(obj, 'to_dict'):
77            return obj.to_dict()
78        # Return obj as-is if it is not a dict or does not have to_dict()
79        return obj
def to_dict(self) -> Dict[str, Any]:
 81    def to_dict(self) -> Dict[str, Any]:
 82        """
 83        Converts the LayoutConfig into a dictionary format that can be
 84        passed into the layout constructor. Handles nested rows and cols.
 85        """
 86        # Create config_dict by excluding None values
 87        config_dict = {k: v for k, v in self.__dict__.items() if v is not None}
 88
 89        # Convert rows and columns to dictionaries, ensuring nested dicts are handled
 90        if self.rows:
 91            config_dict['rows'] = [
 92                self.process_nested_dict(cell) for cell in self.rows
 93            ]
 94
 95        if self.cols:
 96            config_dict['cols'] = [
 97                self.process_nested_dict(cell) for cell in self.cols
 98        ]
 99
100        return config_dict

Converts the LayoutConfig into a dictionary format that can be passed into the layout constructor. Handles nested rows and cols.

class CellConfig:
 5class CellConfig:
 6    """
 7    Configuration class for individual cells in the Layout.
 8    Defines properties like header, id, width, height, etc.
 9    """
10    def __init__(self,
11                 id: str = None,
12                 header: str = None,
13                 width: Union[str, int] = None,
14                 height: Union[str, int] = None,
15                 css: str = None,
16                 collapsable: bool = False,
17                 hidden: bool = False):
18        """
19        :param header: (Optional) Header text of the cell.
20        :param id: (Optional) Unique identifier for the cell.
21        :param width: (Optional) Width of the cell, can be percentage or fixed.
22        :param height: (Optional) Height of the cell, can be percentage or fixed.
23        :param css: (Optional) CSS class to apply to the cell.
24        :param collapsable: (Optional) Whether the cell can be collapsed.
25        :param hidden: (Optional) Whether the cell is hidden by default.
26        """
27        self.header = header
28        self.id = id
29        self.width = width
30        self.height = height
31        self.css = css
32        self.collapsable = collapsable
33        self.hidden = hidden
34
35    def to_dict(self) -> Dict[str, Any]:
36        """
37        Converts the CellConfig into a dictionary format that can be
38        passed into the layout constructor.
39        """
40        return {k: v for k, v in self.__dict__.items() if v is not None}

Configuration class for individual cells in the Layout. Defines properties like header, id, width, height, etc.

CellConfig( id: str = None, header: str = None, width: Union[str, int] = None, height: Union[str, int] = None, css: str = None, collapsable: bool = False, hidden: bool = False)
10    def __init__(self,
11                 id: str = None,
12                 header: str = None,
13                 width: Union[str, int] = None,
14                 height: Union[str, int] = None,
15                 css: str = None,
16                 collapsable: bool = False,
17                 hidden: bool = False):
18        """
19        :param header: (Optional) Header text of the cell.
20        :param id: (Optional) Unique identifier for the cell.
21        :param width: (Optional) Width of the cell, can be percentage or fixed.
22        :param height: (Optional) Height of the cell, can be percentage or fixed.
23        :param css: (Optional) CSS class to apply to the cell.
24        :param collapsable: (Optional) Whether the cell can be collapsed.
25        :param hidden: (Optional) Whether the cell is hidden by default.
26        """
27        self.header = header
28        self.id = id
29        self.width = width
30        self.height = height
31        self.css = css
32        self.collapsable = collapsable
33        self.hidden = hidden
Parameters
  • header: (Optional) Header text of the cell.
  • id: (Optional) Unique identifier for the cell.
  • width: (Optional) Width of the cell, can be percentage or fixed.
  • height: (Optional) Height of the cell, can be percentage or fixed.
  • css: (Optional) CSS class to apply to the cell.
  • collapsable: (Optional) Whether the cell can be collapsed.
  • hidden: (Optional) Whether the cell is hidden by default.
header
id
width
height
css
collapsable
hidden
def to_dict(self) -> Dict[str, Any]:
35    def to_dict(self) -> Dict[str, Any]:
36        """
37        Converts the CellConfig into a dictionary format that can be
38        passed into the layout constructor.
39        """
40        return {k: v for k, v in self.__dict__.items() if v is not None}

Converts the CellConfig into a dictionary format that can be passed into the layout constructor.