1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19
20-module(ex_gauge).
21
22-behaviour(wx_object).
23
24-include_lib("wx/include/wx.hrl").
25
26-export([start/1, init/1, terminate/2,  code_change/3,
27	 handle_info/2, handle_call/3, handle_cast/2, handle_event/2]).
28
29-record(gauge, {obj,
30		value,
31		timer,
32		range
33	       }).
34
35-record(state,
36	{
37	  parent,
38	  config,
39	  normal_gauge,
40	  undeterminate_gauge,
41	  simulate_button,
42	  simulate_undet_button
43	 }).
44
45-define(ID_START_STOP, 1).
46-define(ID_START_STOP_UNDET, 2).
47-define(SET_VALUE, 3).
48-define(VERTICAL, 4).
49
50start(Config) ->
51    wx_object:start_link(?MODULE, Config, []).
52
53%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54init(Config) ->
55        wx:batch(fun() -> do_init(Config) end).
56do_init(Config) ->
57    Parent = proplists:get_value(parent, Config),
58    Panel = wxPanel:new(Parent, []),
59
60    %% Setup sizers
61    MainSizer = wxBoxSizer:new(?wxVERTICAL),
62    AlignSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
63				      [{label, "wxGauge"}]),
64
65    %% Create two horizontal gauges with range 0-100
66    Range = 100,
67    NormalGauge = wxGauge:new(Panel, 1, Range, [{size, {200, -1}},
68						{style, ?wxGA_HORIZONTAL}]),
69    UndetGauge = wxGauge:new(Panel, 2, Range, [{size, {200, -1}},
70					       {style, ?wxGA_HORIZONTAL}]),
71
72    %% Add to sizers
73    wxSizer:add(AlignSizer, NormalGauge, [{flag, ?wxEXPAND}]),
74    wxSizer:add(AlignSizer, UndetGauge, [{flag, ?wxEXPAND}]),
75    {OptSizer, SimulateButton, SimulateUndetermButton}
76	= create_option_sizer(Panel),
77
78    wxSizer:add(MainSizer, AlignSizer, [{flag, ?wxEXPAND}]),
79    wxSizer:add(MainSizer, OptSizer, []),
80
81    wxWindow:connect(Panel, command_togglebutton_clicked),
82    wxWindow:connect(Panel, command_button_clicked),
83
84    wxPanel:setSizer(Panel, MainSizer),
85    {Panel, #state{parent=Panel, config=Config,
86		   normal_gauge = #gauge{obj=NormalGauge, value = 0,
87					 range = Range},
88		   undeterminate_gauge = #gauge{obj=UndetGauge, value = 0,
89					range = Range},
90		   simulate_button = SimulateButton,
91		   simulate_undet_button = SimulateUndetermButton}}.
92
93%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94%% Callbacks handled as normal gen_server callbacks
95handle_info(tick, State=#state{normal_gauge = Gauge=#gauge{obj = Obj,
96							   value = Value,
97							   timer = Timer,
98							   range = Range},
99			       simulate_button = Button}) ->
100    Timer2 =
101	if Value >= Range ->
102		wxToggleButton:setValue(Button, false),
103		wxToggleButton:setLabel(Button, "Simulate load"),
104		wxGauge:setValue(Obj, Range),
105		demo:format(State#state.config, "Simulation finished.\n", []),
106		Timer;
107	   true ->
108		simulate_load(Obj, Value)
109
110	end,
111    {noreply, State#state{normal_gauge = Gauge#gauge{value = Value+5,
112						     timer = Timer2}}};
113handle_info(pulse, State=#state{undeterminate_gauge = Gauge=#gauge{obj = Obj}}) ->
114    wxGauge:pulse(Obj),
115    Timer = erlang:send_after(300, self(), pulse),
116    {noreply, State#state{undeterminate_gauge = Gauge#gauge{timer = Timer}}}.
117
118handle_call(shutdown, _From, State=#state{parent=Panel}) ->
119    wxPanel:destroy(Panel),
120    {stop, normal, ok, State};
121
122handle_call(Msg, _From, State) ->
123    demo:format(State#state.config,"Got Call ~p\n",[Msg]),
124    {reply,ok, State}.
125
126handle_cast(Msg, State) ->
127    io:format("Got cast ~p~n",[Msg]),
128    {noreply,State}.
129
130%% Async Events are handled in handle_event as in handle_info
131handle_event(#wx{id = ?ID_START_STOP,
132		 event = #wxCommand{type = command_togglebutton_clicked,
133				    commandInt = Int}},
134	     State = #state{normal_gauge = #gauge{obj=Gauge,
135						  value = Value,
136						  timer = Timer},
137			    simulate_button = Button}) ->
138    case Int of
139	1 ->
140	    wxToggleButton:setLabel(Button, "Stop simulation"),
141	    simulate_load(Gauge, Value);
142	0 ->
143	    erlang:cancel_timer(Timer),
144	    wxToggleButton:setLabel(Button, "Simulate load"),
145	    ok
146    end,
147    {noreply, State};
148handle_event(#wx{id = ?ID_START_STOP_UNDET,
149		 event = #wxCommand{type = command_togglebutton_clicked,
150				    commandInt = Int}},
151	     State = #state{undeterminate_gauge = G = #gauge{obj=Gauge,
152						    timer = Timer},
153			    simulate_undet_button = Button}) ->
154    Timer2 =
155	case Int of
156	    1 ->
157		wxToggleButton:setLabel(Button, "Stop simulation"),
158		wxGauge:pulse(Gauge),
159		erlang:send_after(300, self(), pulse);
160	    0 ->
161		wxToggleButton:setLabel(Button, "Simulate undeterminate load"),
162		reset(G),
163		undefined
164    end,
165    case Timer of
166	undefined -> ok;
167	_         -> erlang:cancel_timer(Timer)
168    end,
169    {noreply, State#state{undeterminate_gauge = G#gauge{timer = Timer2}}};
170handle_event(#wx{id = ?wxID_CLEAR,
171		 event = #wxCommand{type = command_button_clicked}},
172	    State = #state{normal_gauge = Gauge,
173			   undeterminate_gauge = Gauge2}) ->
174    reset(Gauge),
175    reset(Gauge2),
176    {noreply, State#state{normal_gauge = Gauge#gauge{value = 0}}};
177handle_event(Ev = #wx{}, State = #state{}) ->
178    demo:format(State#state.config,"Got Event ~p\n",[Ev]),
179    {noreply, State}.
180
181code_change(_, _, State) ->
182    {stop, ignore, State}.
183
184terminate(_Reason, _State) ->
185    ok.
186
187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188%% Local functions
189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190
191simulate_load(Gauge, Value) ->
192    wxGauge:setValue(Gauge, Value),
193    erlang:send_after(300, self(), tick).
194
195reset(#gauge{obj = Gauge}) ->
196    wxGauge:setValue(Gauge, 0).
197
198
199create_option_sizer(Panel) ->
200    OptSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
201				    [{label, "Options"}]),
202
203    SimulateButton = wxToggleButton:new(Panel, ?ID_START_STOP, "Simulate load",
204					[{size, {200, 35}}]),
205    SimulateUndetermButton = wxToggleButton:new(Panel, ?ID_START_STOP_UNDET,
206						"Simulate Undeterminate load",
207					[{size, {200, 35}}]),
208    ClearButton = wxButton:new(Panel, ?wxID_CLEAR,
209			       [{size, {200, 35}}]),
210
211    wxSizer:add(OptSizer, SimulateButton),
212    wxSizer:add(OptSizer, SimulateUndetermButton),
213    wxSizer:add(OptSizer, ClearButton),
214
215    wxWindow:connect(Panel, command_checkbox_clicked),
216
217    {OptSizer, SimulateButton, SimulateUndetermButton}.
218