1. Don't try to use 'locale' to control formatting, rather set up your own
user-defined parameter.
2. Use separate parameters for input and display purposes.
It may be an idea to
- use user-defined parameter(s!) for input and display/editing of input
- but use the locale to *output* what the control thinks the
user entered (which may get displayed next to the input
in, say, a small font in its own space, or as a
tooltippish thingy)
- it may be useful (regardless of the above) to have a
dynamic tooltip display the value formatted into a locale
dependant (month name) string so that no ambiguities *can*
arise: 3 M�rz 2010 is not ambigous while 3/3/2010 or
2010-3-3 or whatever all are
I also took the point that you may need to set up preferences for each
user, but this need not form part of a standard control.
I agree.
The control needs
an input parameter containing the desired format
Or a list of (distinct) formats ?
, but it is up to the
application to decide where to get the parameter from.
Yep.
At this stage I do not have a need to input 'time' data, and I do not have
a need for the sophisticated functionality that Karsten mentioned, that
can parse user input into a date/time using a variety of methods,
prompting the user for a decision if necessary.
Where to from here? I can modify my example to incorporate parameters for
input and display purposes, and repost it.
Sure. How about working on it on the wxPython wiki ?
The TextCtrlAutoComplete example may give you more ideas
should any be needed.
Feel free to lift whatever code you want from the GNUmed
control as well !
However, I will wait a bit to give others a chance to add their requests,
if any. If any of those features are already part of GNUmed, then perhaps
Karsten can take my example as a base and copy/paste some of GNUmed's
functionality into it.
Not exactly but once it's in the wiki I am likely to work on
it a bit at some point (say, a night shift and no patients).
Of course this presupposes that my example is a good base to start from.
Sure. I really like the part about the calendar.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import division
from __future__ import print_function
It doesn't look like those are used, are they ?
import sys
import wx
import wx.calendar
import wx.combo
from datetime import date as dt
class MyDateCtrl(wx.combo.ComboCtrl):
def __init__(self, parent, size, pos, title):
wx.combo.ComboCtrl.__init__(self, parent, size=size, pos=pos)
self.title = title
self.TextCtrl.Bind(wx.EVT_SET_FOCUS, self.on_got_focus)
self.TextCtrl.Bind(wx.EVT_KILL_FOCUS, self.on_lost_focus)
self.TextCtrl.Bind(wx.EVT_CHAR, self.on_char)
self.nav = False
self.setup_button()
def setup_button(self): # copied directly from demo
# make a custom bitmap showing "..."
bw, bh = 14, 16
bmp = wx.EmptyBitmap(bw, bh)
dc = wx.MemoryDC(bmp)
# clear to a specific background colour
bgcolor = wx.Colour(255, 254, 255)
dc.SetBackground(wx.Brush(bgcolor))
dc.Clear()
# draw the label onto the bitmap
label = "..."
Just to make sure you're aware of it: there's a unicode
codepoint for a nice ellipsis:
u_ellipsis = u'\u2026'
Here's a bunch of others:
u_right_double_angle_quote = u'\u00AB' # <<
u_registered_trademark = u'\u00AE'
u_plus_minus = u'\u00B1'
u_left_double_angle_quote = u'\u00BB' # >>
u_one_quarter = u'\u00BC'
u_one_half = u'\u00BD'
u_three_quarters = u'\u00BE'
u_ellipsis = u'\u2026'
u_left_arrow = u'\u2190' # -->
u_right_arrow = u'\u2192' # <--
u_sum = u'\u2211'
u_corresponds_to = u'\u2258'
u_infinity = u'\u221E'
u_diameter = u'\u2300'
u_checkmark_crossed_out = u'\u237B'
u_frowning_face = u'\u2639'
u_smiling_face = u'\u263a'
u_black_heart = u'\u2665'
u_checkmark_thin = u'\u2713'
u_checkmark_thick = u'\u2714'
u_writing_hand = u'\u270d'
u_pencil_1 = u'\u270e'
u_pencil_2 = u'\u270f'
u_pencil_3 = u'\u2710'
u_latin_cross = u'\u271d'
u_replacement_character = u'\ufffd'
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
font.SetWeight(wx.FONTWEIGHT_BOLD)
dc.SetFont(font)
tw, th = dc.GetTextExtent(label)
dc.DrawText(label, (bw-tw)/2, (bw-tw)/2)
del dc
# now apply a mask using the bgcolor
bmp.SetMaskColour(bgcolor)
# and tell the ComboCtrl to use it
self.SetButtonBitmaps(bmp, True)
# Overridden from ComboCtrl, called when the combo button is clicked
def OnButtonClick(self):
text_ctrl = self.TextCtrl
date = text_ctrl.Value
if date in ('', ' / / '):
wx_date = wx.DateTime()
else:
d, m, y = map(int, date.split('/'))
wx_date = wx.DateTimeFromDMY(d, m-1, y)
dlg = MyCalendarDlg(self, wx_date)
dlg.CentreOnScreen()
Maybe you can calculate the position of the date picker from
which the calendar was invoked and somehow align to that ?
Say, align the top left calendar corner to the bottom left
corner of the picker ? This might add some visual
consistency.
if dlg.ShowModal() == wx.ID_OK:
cal_date = dlg.cal.Date
text_ctrl.Value = '{0:02}/{1:02}/{2:04}'.format(
cal_date.Day, cal_date.Month+1, cal_date.Year)
self.nav = True
dlg.Destroy()
self.SetFocus()
# Overridden from ComboCtrl to avoid assert since there is no ComboPopup
def DoSetPopupControl(self, popup):
pass
def on_got_focus(self, evt):
if self.nav: # user has made a selection, so move on
self.nav = False
wx.CallAfter(self.Navigate)
else:
text_ctrl = self.TextCtrl
if text_ctrl.Value == '':
text_ctrl.Value = ' / / '
text_ctrl.InsertionPoint = 0
text_ctrl.SetSelection(-1, -1)
text_ctrl.pos = 0
evt.Skip()
def on_lost_focus(self, evt):
value = self.Value
if value == ' / / ': # ) remove these lines
self.Value = '' # ) if you want a blank
evt.Skip() # ) entry to default to
return # ) today's date
today = dt.today()
date = value.split('/')
day = date[0].strip()
if day == '':
day = today.day
else:
day = int(day)
month = date[1].strip()
if month == '':
month = today.month
else:
month = int(month)
year = date[2].strip()
if year == '':
year = today.year
elif len(year) == 2:
# assume year is in range (today-75) to (today+25)
year = int(year) + int(today.year/100)*100
if year - today.year > 25:
year -= 100
elif year - today.year < -75:
year += 100
else:
year = int(year)
try:
date = dt(year, month, day)
self.Value = '{0:02}/{1:02}/{2:04}'.format(day, month, year)
except ValueError as error:
dlg = wx.MessageDialog(
self, str(error), self.title, wx.OK | wx.ICON_INFORMATION)
This str(error) seems mighty optimistic to me.
dlg.ShowModal()
dlg.Destroy()
wx.CallAfter(self.SetFocus)
self.TextCtrl.SetSelection(0, 0)
evt.Skip()
def on_char(self, evt):
text_ctrl = self.TextCtrl
code = evt.KeyCode
if code in (wx.WXK_SPACE, wx.WXK_F4) and not evt.AltDown():
self.OnButtonClick()
return
if code in (wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_HOME, wx.WXK_END):
if text_ctrl.Selection == (0, 10):
text_ctrl.SetSelection(0, 0)
if code == wx.WXK_LEFT:
if text_ctrl.pos > 0:
text_ctrl.pos -= 1
if text_ctrl.pos in (2, 5):
text_ctrl.pos -= 1
elif code == wx.WXK_RIGHT:
if text_ctrl.pos < 10:
text_ctrl.pos += 1
if text_ctrl.pos in (2, 5):
text_ctrl.pos += 1
elif code == wx.WXK_HOME:
text_ctrl.pos = 0
elif code == wx.WXK_END:
text_ctrl.pos = 10
text_ctrl.InsertionPoint = text_ctrl.pos
return
if code in (wx.WXK_BACK, wx.WXK_DELETE):
if text_ctrl.Selection == (0, 10):
text_ctrl.Value = ' / / '
text_ctrl.SetSelection(0, 0)
if code == wx.WXK_BACK:
if text_ctrl.pos == 0:
return
text_ctrl.pos -= 1
if text_ctrl.pos in (2, 5):
text_ctrl.pos -= 1
elif code == wx.WXK_DELETE:
if text_ctrl.pos == 10:
return
curr_val = text_ctrl.Value
text_ctrl.Value = curr_val[:text_ctrl.pos]+' '+curr_val[text_ctrl.pos+1:]
text_ctrl.InsertionPoint = text_ctrl.pos
return
if code in (wx.WXK_TAB, wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER) or code > 255:
evt.Skip()
return
if text_ctrl.pos == 10:
wx.Bell()
return
ch = chr(code)
unichr(evt.GetUnicodeKey()) ?
if ch not in ('0123456789'):
wx.Bell()
return
You may want to verify against a regular expression.
if text_ctrl.Selection == (0, 10):
curr_val = ' / / '
else:
curr_val = text_ctrl.Value
text_ctrl.Value = curr_val[:text_ctrl.pos]+ch+curr_val[text_ctrl.pos+1:]
text_ctrl.pos += 1
if text_ctrl.pos in (2, 5):
text_ctrl.pos += 1
text_ctrl.InsertionPoint = text_ctrl.pos
class MyCalendarDlg(wx.Dialog):
def __init__(self, parent, date):
wx.Dialog.__init__(self, parent, title=parent.title)
panel = wx.Panel(self, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(sizer)
cal = wx.calendar.CalendarCtrl(panel, date=date)
if sys.platform != 'win32':
# gtk truncates the year - this fixes it
I seem to remember a display-century type flag on calendar
controls. Would that help ?
w, h = cal.Size
cal.Size = (w+25, h)
cal.MinSize = cal.Size
Karsten
···
On Wed, Jun 30, 2010 at 07:41:54AM +0200, frank@chagford.com wrote:
--
GPG key ID E4071346 @ wwwkeys.pgp.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346