Skip to content

Commit

Permalink
Add Root URL, Add Group: Reorder fields. Mark required fields. Add pl…
Browse files Browse the repository at this point in the history
…aceholder text.
  • Loading branch information
davidfstr committed Dec 25, 2023
1 parent f2ee349 commit b5c9843
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 47 deletions.
22 changes: 12 additions & 10 deletions src/crystal/browser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
from crystal.browser.entitytree import EntityTree
from crystal.browser.preferences import PreferencesDialog
from crystal.browser.tasktree import TaskTree
from crystal.model import Project, Resource, ResourceGroup, RootResource
from crystal.model import (
Project, Resource, ResourceGroup, ResourceGroupSource, RootResource
)
from crystal.progress import (
CancelLoadUrls,
DummyOpenProjectProgressListener,
Expand Down Expand Up @@ -342,25 +344,25 @@ def _create_button_bar(self, parent: wx.Window):
# === Entity Pane: Properties ===

@property
def _selection_initial_url(self):
def _selection_initial_url(self) -> Optional[str]:
selected_entity = self.entity_tree.selected_entity
if type(selected_entity) in (Resource, RootResource):
if isinstance(selected_entity, (Resource, RootResource)):
return selected_entity.resource.url
elif type(selected_entity) is ResourceGroup:
elif isinstance(selected_entity, ResourceGroup):
return selected_entity.url_pattern
else:
return self.project.default_url_prefix

@property
def _selection_initial_source(self):
def _selection_initial_source(self) -> Optional[ResourceGroupSource]:
selected_entity = self.entity_tree.selected_entity
if type(selected_entity) in (Resource, RootResource):
if isinstance(selected_entity, (Resource, RootResource)):
parent_of_selected_entity = self.entity_tree.parent_of_selected_entity
if type(parent_of_selected_entity) in (ResourceGroup, RootResource):
if isinstance(parent_of_selected_entity, (ResourceGroup, RootResource)):
return parent_of_selected_entity
else:
return None
elif type(selected_entity) is ResourceGroup:
elif isinstance(selected_entity, ResourceGroup):
return selected_entity.source
else:
return None
Expand Down Expand Up @@ -421,7 +423,7 @@ def _on_close_frame(self, event: wx.CloseEvent) -> None:
def _on_add_url(self, event: wx.CommandEvent) -> None:
AddRootUrlDialog(
self._frame, self._on_add_url_dialog_ok,
initial_url=self._selection_initial_url)
initial_url=self._selection_initial_url or '')

def _on_add_url_dialog_ok(self, name, url) -> None:
# TODO: Validate user input:
Expand All @@ -434,7 +436,7 @@ def _on_add_group(self, event: wx.CommandEvent) -> None:
AddGroupDialog(
self._frame, self._on_add_group_dialog_ok,
self.project,
initial_url=self._selection_initial_url,
initial_url=self._selection_initial_url or '',
initial_source=self._selection_initial_source)
except CancelLoadUrls:
pass
Expand Down
51 changes: 33 additions & 18 deletions src/crystal/browser/addgroup.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from crystal.model import ResourceGroup
# TODO: Consider extracting functions shared between dialogs to own module
from crystal.browser.addrooturl import AddRootUrlDialog, fields_hide_hint_when_focused
from crystal.model import Project, ResourceGroup, ResourceGroupSource
from crystal.progress import CancelLoadUrls
from crystal.util.wx_bind import bind
from crystal.util.wx_dialog import position_dialog_initially
from crystal.util.wx_static_box_sizer import wrap_static_box_sizer_child
from crystal.util.xos import is_linux
import sys
from typing import Union
from typing import Callable, Optional, Union
import wx


Expand All @@ -19,11 +21,17 @@ class AddGroupDialog:

# === Init ===

def __init__(self, parent, on_finish, project, initial_url=None, initial_source=None) -> None:
def __init__(self,
parent: wx.Window,
on_finish: Callable[[str, str, ResourceGroupSource], None],
project: Project,
initial_url: str='',
initial_source: Optional[ResourceGroupSource]=None,
) -> None:
"""
Arguments:
* parent -- parent wx.Window that this dialog is attached to.
* on_finish -- called when OK pressed on dialog. Is a callable(name, url_pattern).
* on_finish -- called when OK pressed on dialog. Is a callable(name, url_pattern, source).
* project -- the project.
* initial_url -- overrides the initial URL displayed.
* initial_source -- overrides the initial source displayed.
Expand All @@ -33,8 +41,6 @@ def __init__(self, parent, on_finish, project, initial_url=None, initial_source=
"""
self._project = project
self._on_finish = on_finish
if initial_url is None:
initial_url = 'http://'

# Show progress dialog in advance if will need to load all project URLs
try:
Expand Down Expand Up @@ -92,42 +98,43 @@ def __init__(self, parent, on_finish, project, initial_url=None, initial_source=
dialog_sizer.Add(dialog.CreateButtonSizer(wx.OK|wx.CANCEL), flag=wx.EXPAND|wx.BOTTOM,
border=_WINDOW_INNER_PADDING)

self.name_field.SetFocus()
if not fields_hide_hint_when_focused():
self.pattern_field.SetFocus() # initialize focus
self._update_preview_urls()

position_dialog_initially(dialog)
dialog.Show(True)
dialog.Fit()

def _create_fields(self, parent: wx.Window, initial_url: str, initial_source) -> wx.Sizer:
def _create_fields(self,
parent: wx.Window,
initial_url: str,
initial_source: Optional[ResourceGroupSource]
) -> wx.Sizer:
fields_sizer = wx.FlexGridSizer(cols=2,
vgap=_FORM_ROW_SPACING, hgap=_FORM_LABEL_INPUT_SPACING)
fields_sizer.AddGrowableCol(1)

fields_sizer.Add(wx.StaticText(parent, label='Name:', style=wx.ALIGN_RIGHT), flag=wx.EXPAND)
self.name_field = wx.TextCtrl(
parent,
name='cr-add-group-dialog__name-field')
self.name_field.SetSelection(-1, -1)
fields_sizer.Add(self.name_field, flag=wx.EXPAND)

pattern_field_sizer = wx.BoxSizer(wx.VERTICAL)
self.pattern_field = wx.TextCtrl(
parent, value=initial_url, size=(300,-1), # width hint
name='cr-add-group-dialog__pattern-field')
bind(self.pattern_field, wx.EVT_TEXT, self._on_pattern_field_changed)
self.pattern_field.SetSelection(-1, -1)
self.pattern_field.Hint = 'https://example.com/post/*'
self.pattern_field.SetSelection(-1, -1) # select all upon focus
pattern_field_sizer.Add(self.pattern_field, flag=wx.EXPAND)
pattern_field_sizer.Add(wx.StaticText(parent, label='# = digit, @ = alpha, * = any nonslash, ** = any'), flag=wx.EXPAND)

fields_sizer.Add(wx.StaticText(parent, label='URL Pattern:', style=wx.ALIGN_RIGHT|wx.ALIGN_TOP), flag=wx.EXPAND)
pattern_label = wx.StaticText(parent, label='URL Pattern:', style=wx.ALIGN_RIGHT|wx.ALIGN_TOP)
pattern_label.Font = pattern_label.Font.Bold() # mark as required
fields_sizer.Add(pattern_label, flag=wx.EXPAND)
fields_sizer.Add(pattern_field_sizer, flag=wx.EXPAND)

fields_sizer.Add(wx.StaticText(parent, label='Source:', style=wx.ALIGN_RIGHT), flag=wx.EXPAND)
self.source_choice_box = wx.Choice(
parent,
name='cr-add-group-dialog__source-field')
self.source_choice_box.Append('None', None)
self.source_choice_box.Append('none', None)
for rr in self._project.root_resources:
self.source_choice_box.Append(rr.name, rr)
for rg in self._project.resource_groups:
Expand All @@ -141,6 +148,14 @@ def _create_fields(self, parent: wx.Window, initial_url: str, initial_source) ->
break
fields_sizer.Add(self.source_choice_box, flag=wx.EXPAND)

fields_sizer.Add(wx.StaticText(parent, label='Name:', style=wx.ALIGN_RIGHT), flag=wx.EXPAND)
self.name_field = wx.TextCtrl(
parent,
name='cr-add-group-dialog__name-field')
self.name_field.Hint = 'Post'
self.name_field.SetSelection(-1, -1) # select all upon focus
fields_sizer.Add(self.name_field, flag=wx.EXPAND)

return fields_sizer

def _create_preview_box_content(self, parent: wx.Window) -> wx.Sizer:
Expand Down
51 changes: 32 additions & 19 deletions src/crystal/browser/addrooturl.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from crystal.util.wx_bind import bind
from crystal.util.wx_dialog import position_dialog_initially
from crystal.util.xos import is_wx_gtk
from typing import Callable
import wx


Expand All @@ -11,16 +13,18 @@
class AddRootUrlDialog:
# === Init ===

def __init__(self, parent, on_finish, initial_url=None):
def __init__(self,
parent: wx.Window,
on_finish: Callable[[str, str], None],
initial_url: str='',
) -> None:
"""
Arguments:
* parent -- parent wx.Window that this dialog is attached to.
* on_finish -- called when OK pressed on dialog. Is a callable(name, url).
* initial_url -- overrides the initial URL displayed.
"""
self._on_finish = on_finish
if initial_url is None:
initial_url = 'http://'

dialog = self.dialog = wx.Dialog(parent, title='New Root URL', name='cr-add-url-dialog')
dialog_sizer = wx.BoxSizer(wx.VERTICAL)
Expand All @@ -33,52 +37,61 @@ def __init__(self, parent, on_finish, initial_url=None):
dialog_sizer.Add(dialog.CreateButtonSizer(wx.OK|wx.CANCEL), flag=wx.EXPAND|wx.BOTTOM,
border=_WINDOW_INNER_PADDING)

self.name_field.SetFocus()
if not fields_hide_hint_when_focused():
self.url_field.SetFocus() # initialize focus

position_dialog_initially(dialog)
dialog.Show(True)
dialog.Fit() # NOTE: Must Fit() after Show() here so that wxGTK actually fits correctly

def _create_fields(self, parent, initial_url):
def _create_fields(self, parent: wx.Window, initial_url: str) -> wx.Sizer:
fields_sizer = wx.FlexGridSizer(rows=2, cols=2,
vgap=_FORM_ROW_SPACING, hgap=_FORM_LABEL_INPUT_SPACING)
fields_sizer.AddGrowableCol(1)

fields_sizer.Add(wx.StaticText(parent, label='Name:', style=wx.ALIGN_RIGHT), flag=wx.EXPAND)
self.name_field = wx.TextCtrl(
parent,
name='cr-add-url-dialog__name-field')
self.name_field.SetSelection(-1, -1)
fields_sizer.Add(self.name_field, flag=wx.EXPAND)
url_label = wx.StaticText(parent, label='URL:', style=wx.ALIGN_RIGHT)
url_label.Font = url_label.Font.Bold() # mark as required
fields_sizer.Add(url_label, flag=wx.EXPAND)

fields_sizer.Add(wx.StaticText(parent, label='URL:', style=wx.ALIGN_RIGHT), flag=wx.EXPAND)
self.url_field = wx.TextCtrl(
parent, value=initial_url, size=(300,-1), # width hint
name='cr-add-url-dialog__url-field')
self.url_field.SetSelection(-1, -1)
self.url_field.Hint = 'https://example.com/'
self.url_field.SetSelection(-1, -1) # select all upon focus
fields_sizer.Add(self.url_field, flag=wx.EXPAND)

fields_sizer.Add(wx.StaticText(parent, label='Name:', style=wx.ALIGN_RIGHT), flag=wx.EXPAND)

self.name_field = wx.TextCtrl(
parent,
name='cr-add-url-dialog__name-field')
self.url_field.Hint = 'Home'
self.name_field.SetSelection(-1, -1) # select all upon focus
fields_sizer.Add(self.name_field, flag=wx.EXPAND)

return fields_sizer

# === Events ===

def _on_button(self, event):
def _on_button(self, event: wx.CommandEvent) -> None:
btn_id = event.GetEventObject().GetId()
if btn_id == wx.ID_OK:
self._on_ok(event)
elif btn_id == wx.ID_CANCEL:
self._on_cancel(event)

def _on_close(self, event):
def _on_close(self, event: wx.CommandEvent) -> None:
self._on_cancel(event)

def _on_ok(self, event):
def _on_ok(self, event: wx.CommandEvent) -> None:
name = self.name_field.GetValue()
url = self.url_field.GetValue()
self._on_finish(name, url)
self.dialog.Destroy()

def _on_cancel(self, event):
def _on_cancel(self, event: wx.CommandEvent) -> None:
self.dialog.Destroy()




def fields_hide_hint_when_focused() -> bool:
return is_wx_gtk()

0 comments on commit b5c9843

Please sign in to comment.