[erlang-questions] wxDatePickerCtrl and invalid value

Joakim Hirsch <>
Wed Dec 3 00:32:22 CET 2014


Hi,

I've run into a problem with the wxDatePickerCtrl when creating it with 
flag ?wxDP_ALLOWNONE. This flag allows the control to have an 
undefined/invalid value. The control is adorned with a checkbox, which 
is checked if the value is defined/valid. When the control is created, 
the checkbox is unchecked (invalid). Retrieving the value renders "the 
invalid value" {{1970, 1, 1}, {0, 59, 59}}. I need to be able to reset 
the value of the control to invalid sometimes, but the interface of 
wxDatePickerCtrl doesn't offer a reset or any way to affect the checkbox.

One idea is to set the control value to the invalid value, but that 
doesn't do it. The control will return {{1970, 1, 1}, {0, 0, 0}} and the 
checkbox is checked (valid).

It would perhaps have been possible to work around this by replacing the 
control with a new one. It would be necessary to get the parent and 
containing sizer and to copy name, size, style (and id but I'm not using 
it), and range -- all quite possible, except for the range. The function
wxDatePickerCtrl:getRange(This, Dt1, Dt2) -> boolean()
does not return the range. The wxWidgets method is defined as
boolean GetRange(wxDateTime*dt1, wxDateTime* dt2) const
and will fill the supplied parameters with the range values in a C way.

So my next idea is to combine a checkbox and a date picker (without the 
allow-none style) myself. Maybe someone has a better suggestion, or can 
teach me how to work the date picker?

I'm running Erlang/OTP 17

Here's a sample. All the interesting stuff is in do_init/1. Any help 
would be much appreciated.
BR
Joakim Hirsch

-module(test_gui).

-behaviour(wx_object).

%% Client API
-export([start/0]).

%% wx_object callbacks
-export([init/1, terminate/2,  code_change/3,
      handle_info/2, handle_call/3, handle_cast/2, handle_event/2,
      handle_sync_event/3]).

-include_lib("wx/include/wx.hrl").

-record(state,
     {
       parent
     }).


start() ->
     Wx = wx:new(),
     Size = {size, {500, 500}},
     Frame = wxFrame:new(Wx, ?wxID_ANY, "Title", [Size]),
     Config = [{parent, Frame}],
     wx_object:start_link(?MODULE, Config, []).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init(Config) ->
     wx:batch(fun() -> do_init(Config) end).

do_init(Config) ->
     Frame = proplists:get_value(parent, Config),
     Panel = wxPanel:new(Frame),
     Style = ?wxDP_DROPDOWN bor ?wxDP_ALLOWNONE,
     Ctrl = wxDatePickerCtrl:new(Panel, ?wxID_ANY, [{style, Style},
                            {size, {200, -1}}]),
     wxFrame:show(Frame),

     %% Ctrl displays todays date but the
     %% checkbox is unchecked <=> invalid value
     timer:sleep(5000),

     %% Value is "the invalid value".
     Invalid = {{1970, 1, 1}, {0, 59, 59}},
     Invalid = wxDatePickerCtrl:getValue(Ctrl),

     wxDatePickerCtrl:setValue(Ctrl, Invalid),

     %% Ctrl displays {1970, 1, 1}
     %% Checkbox is now checked <=> valid value

     %% Value is not invalid anymore.
     Valid = {{1970, 1, 1}, {0, 0, 0}},
     Valid = wxDatePickerCtrl:getValue(Ctrl),

     {Frame, #state{parent = Frame}}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Sync events i.e. from callbacks must return ok, it can not return a
%% new state.  Do the redrawing here.
handle_sync_event(#wx{event = #wxPaint{}},_,
           #state{}) ->
     ok.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Callbacks handled as normal gen_server callbacks
%%


%% Unknown event.
%%
handle_event(Ev = #wx{}, State) ->
     io:format("Got event:~p\n", [Ev]),
     {noreply, State}.

handle_info(Msg, State) ->
     io:format("Got Info ~p\n", [Msg]),
     {noreply, State}.

handle_call(shutdown, _From, State=#state{parent=Frame}) ->
     io:format("Shutdown~n", []),
     wxFrame:destroy(Frame),
     {stop, normal, ok, State};

handle_call(Msg, _From, State) ->
     io:format("Got Call ~p\n", [Msg]),
     {reply, {error, unknown_call}, State}.

handle_cast(Msg, State) ->
     io:format("Got cast ~p~n",[Msg]),
     {noreply, State}.

code_change(_, _, State) ->
     {stop, ignore, State}.

terminate(_Reason, _State) ->
     io:format("Stopping~n", []),
     wx:destroy(),
     ok.



More information about the erlang-questions mailing list