aboutsummaryrefslogtreecommitdiffstats
path: root/lib/wx/src/wx.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/wx/src/wx.erl')
-rw-r--r--lib/wx/src/wx.erl320
1 files changed, 320 insertions, 0 deletions
diff --git a/lib/wx/src/wx.erl b/lib/wx/src/wx.erl
new file mode 100644
index 0000000000..14abd0d817
--- /dev/null
+++ b/lib/wx/src/wx.erl
@@ -0,0 +1,320 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%%-------------------------------------------------------------------
+%%% File : wx.erl
+%%% Author : Dan Gudmundsson <[email protected]>
+%%% Description :
+%%%
+%%% Created : 22 Feb 2007 by Dan Gudmundsson <[email protected]>
+%%%-------------------------------------------------------------------
+
+%% @doc A port of <a href="http://www.wxwidgets.org/">wxWidgets</a>.
+%%
+%% This is the base api of <a href="http://www.wxwidgets.org/">wxWidgets</a>.
+%% This module contains functions for
+%% starting and stopping the wx-server, as well as other utility functions.
+%%
+%% wxWidgets is object oriented, and not functional. Thus, in wxErlang a
+%% module represents a class, and the object created by this class
+%% has an own type, wxCLASS(). This module represents the base
+%% class, and all other wxMODULE's are sub-classes of this class.
+%%
+%% Objects of a class are created with wxCLASS:new(...) and destroyed with
+%% wxCLASS:destroy(). Member functions are called with wxCLASS:member(Object, ...)
+%% instead of as in C++ Object.member(...).
+%%
+%% Sub class modules inherit (non static) functions from their parents.
+%% The inherited functions are not documented in the sub-classes.
+%%
+%% This erlang port of wxWidgets tries to be a one-to-one mapping with
+%% the original wxWidgets library. Some things are different though,
+%% as the optional arguments use property lists and can be in any
+%% order. The main difference is the event handling which is different
+%% from the original library. See {@link wxEvtHandler}.
+%%
+%% The following classes are implemented directly as erlang types: <br />
+%% wxPoint={x,y},wxSize={w,h},wxRect={x,y,w,h},wxColour={r,g,b [,a]},
+%% wxString={@link //stdlib/unicode:charlist()},
+%% wxGBPosition={r,c},wxGBSpan={rs,cs},wxGridCellCoords={r,c}.
+%%
+%% wxWidgets uses a process specific environment, which is created by
+%% {@link wx:new/0}. To be able to use the environment from other
+%% processes, call {@link get_env/0} to retrieve the environment and
+%% {@link set_env/1} to assign the environment in the other process.
+%%
+%% Global (classless) functions are located in the wx_misc module.
+
+%% @type wxObject(). Opaque object
+%% @type wx_env(). Wx process environment
+%% @type wx_mem(). Wx memory area
+%% @type colour(). A 3 or 4 tuple: {R,G,B,A} or as argument {R,G,B} is also accepted
+%% where each colour channel is a an integer between 0-255.
+%% @type datetime(). {{Year,Month,Day}, {Hour,Minute,Second}} in local timezone.
+%% @type mouseState(). See #wxMouseState{} defined in wx.hrl
+
+
+-module(wx).
+
+-export([parent_class/1, new/0, new/1, destroy/0,
+ get_env/0,set_env/1, debug/1,
+ batch/1,foreach/2,map/2,foldl/3,foldr/3,
+ getObjectType/1, typeCast/2,
+ null/0, is_null/1]).
+
+-export([create_memory/1, get_memory_bin/1,
+ retain_memory/1, release_memory/1]).
+
+
+-export([demo/0]).
+
+-include("wxe.hrl").
+
+%% @hidden
+parent_class(_) -> true. %% Let the null pointers be sent down.
+
+%% @spec () -> wxObject()
+%% @doc Starts a wx server.
+new() ->
+ new([]).
+
+%% @spec ([Option]) -> wxObject()
+%% @doc Starts a wx server.
+%% Option may be {debug, Level}, see debug/1.
+new(Options) when is_list(Options) ->
+ #wx_env{} = wxe_server:start(),
+ Debug = proplists:get_value(debug, Options, 0),
+ debug(Debug),
+ null().
+
+%% @spec () -> ok
+%% @doc Stops a wx server.
+destroy() ->
+ wxe_server:stop(),
+ erase(?WXE_IDENTIFIER),
+ ok.
+
+%% @spec () -> wx_env()
+%% @doc Gets this process's current wx environment.
+%% Can be sent to other processes to allow them use this process wx environment.
+%% @see set_env/1
+get_env() ->
+ case get(?WXE_IDENTIFIER) of
+ undefined -> erlang:error({wxe,unknown_port});
+ Env = #wx_env{} -> Env
+ end.
+
+%% @spec (wx_env()) -> ok
+%% @doc Sets the process wx environment, allows this process to use
+%% another process wx environment.
+set_env(#wx_env{sv=Pid} = Env) ->
+ put(?WXE_IDENTIFIER, Env),
+ %% wxe_util:cast(?REGISTER_PID, <<>>),
+ wxe_server:register_me(Pid),
+ ok.
+
+%% @spec () -> wxObject()
+%% @doc Returns the null object
+null() ->
+ #wx_ref{ref=0, type=wx}.
+
+%% @spec (wxObject()) -> boolean()
+%% @doc Returns true if object is null, false otherwise
+is_null(#wx_ref{ref=NULL}) -> NULL =:= 0.
+
+%% @spec (wxObject()) -> atom()
+%% @doc Returns the object type
+getObjectType(#wx_ref{type=Type}) ->
+ Type.
+
+%% @spec (wxObject(), atom()) -> wxObject()
+%% @doc Casts the object to class NewType.
+%% It is needed when using functions like wxWindow:findWindow/2, which
+%% returns a generic wxObject type.
+typeCast(Old=#wx_ref{}, NewType) when is_atom(NewType) ->
+ Old#wx_ref{type=NewType}.
+
+%% @spec (function()) -> term()
+%% @doc Batches all <c>wx</c> commands
+%% used in the fun. Improves performance of the command processing by
+%% grabbing the wxWidgets thread so that no event processing will be
+%% done before the complete batch of commands is invoked.
+%%
+%% @see map/2
+%% @see foreach/2
+%% @see foldl/3
+%% @see foldr/3
+batch(Fun) ->
+ ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
+ try Fun()
+ catch
+ error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ throw:W -> erlang:throw(W);
+ exit:W -> erlang:exit(W)
+ after
+ ok = wxe_util:cast(?BATCH_END, <<>>)
+ end.
+
+%% @spec (function(), list()) -> ok
+%% @doc Behaves like {@link //stdlib/lists:foreach/2} but batches wx commands. See {@link batch/1}.
+foreach(Fun, List) ->
+ ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
+ try lists:foreach(Fun, List)
+ catch
+ error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ throw:W -> erlang:throw(W);
+ exit:W -> erlang:exit(W)
+ after
+ ok = wxe_util:cast(?BATCH_END, <<>>)
+ end.
+
+%% @spec (function(), list()) -> list()
+%% @doc Behaves like {@link //stdlib/lists:map/2} but batches wx commands. See {@link batch/1}.
+map(Fun, List) ->
+ ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
+ try lists:map(Fun, List)
+ catch
+ error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ throw:W -> erlang:throw(W);
+ exit:W -> erlang:exit(W)
+ after
+ ok = wxe_util:cast(?BATCH_END, <<>>)
+ end.
+
+%% @spec (function(), term(), list()) -> term()
+%% @doc Behaves like {@link //stdlib/lists:foldl/3} but batches wx commands. See {@link batch/1}.
+foldl(Fun, Acc, List) ->
+ ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
+ try lists:foldl(Fun, Acc, List)
+ catch
+ error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ throw:W -> erlang:throw(W);
+ exit:W -> erlang:exit(W)
+ after
+ ok = wxe_util:cast(?BATCH_END, <<>>)
+ end.
+
+%% @spec (function(), term(), list()) -> term()
+%% @doc Behaves like {@link //stdlib/lists:foldr/3} but batches wx commands. See {@link batch/1}.
+foldr(Fun, Acc, List) ->
+ ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
+ try lists:foldr(Fun, Acc, List)
+ catch
+ error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ throw:W -> erlang:throw(W);
+ exit:W -> erlang:exit(W)
+ after
+ ok = wxe_util:cast(?BATCH_END, <<>>)
+ end.
+
+-define(MIN_BIN_SIZE, 64). %% Current emulator min off heap size
+
+%% @spec (integer()) -> wx_memory()
+%% @doc Creates a memory area (of Size in bytes) which can be used by an external library (i.e. opengl).
+%% It is up to the client to keep a reference to this object so it does
+%% not get garbage collected by erlang while still in use by the external
+%% library.
+%%
+%% This is far from erlang's intentional usage and can crash the erlang emulator.
+%% Use it carefully.
+create_memory(Size) when Size > ?MIN_BIN_SIZE ->
+ #wx_mem{bin = <<0:(Size*8)>>, size = Size};
+create_memory(Size) ->
+ #wx_mem{bin = <<0:((?MIN_BIN_SIZE+1)*8)>>, size = Size}.
+
+%% @spec (wx_memory()) -> binary()
+%% @doc Returns the memory area as a binary.
+get_memory_bin(#wx_mem{bin=Bin, size=Size}) when Size > ?MIN_BIN_SIZE ->
+ Bin;
+get_memory_bin(#wx_mem{bin=Bin, size=Size}) ->
+ <<WithCorrectSize:Size/binary, _/binary>> = Bin,
+ WithCorrectSize.
+
+%% @spec (wx_memory()) -> ok
+%% @doc Saves the memory from deletion until release_memory/1 is called.
+%% If release_memory/1 is not called the memory will not be garbage collected.
+retain_memory(#wx_mem{bin=Bin}) ->
+ wxe_util:send_bin(Bin),
+ ok = wxe_util:cast(?WXE_BIN_INCR, <<>>);
+retain_memory(Bin) when is_binary(Bin) ->
+ case byte_size(Bin) > ?MIN_BIN_SIZE of
+ true -> ok;
+ false -> erlang:error(small_bin)
+ end,
+ wxe_util:send_bin(Bin),
+ ok = wxe_util:cast(?WXE_BIN_INCR, <<>>).
+
+release_memory(#wx_mem{bin=Bin}) ->
+ wxe_util:send_bin(Bin),
+ ok = wxe_util:cast(?WXE_BIN_DECR, <<>>);
+release_memory(Bin) when is_binary(Bin) ->
+ wxe_util:send_bin(Bin),
+ ok = wxe_util:cast(?WXE_BIN_DECR, <<>>).
+
+
+
+
+%% @spec (Level::term()) -> ok
+%% Level = none | verbose | trace | driver | [Level]
+%% @doc Sets debug level. If debug level is verbose or trace
+%% each call is printed on console. If Level is driver each allocated
+%% object and deletion is printed on the console.
+debug(none) -> debug(0);
+debug(verbose) -> debug(1);
+debug(trace) -> debug(2);
+debug(driver) -> debug(16);
+debug([]) -> debug(0);
+
+debug(List) when is_list(List) ->
+ {Drv,Erl} =
+ lists:foldl(fun(verbose, {Drv,_Erl}) ->
+ {Drv,1};
+ (trace, {Drv,_Erl}) ->
+ {Drv,2};
+ (driver, {_Drv,Erl}) ->
+ {16, Erl}
+ end, {0,0}, List),
+ debug(Drv + Erl);
+debug(Level) when is_integer(Level) ->
+ case get(?WXE_IDENTIFIER) of
+ undefined -> erlang:error({wxe,unknown_port});
+ #wx_env{debug=Old} when Old =:= Level -> ok;
+ Env = #wx_env{sv=Server, port=Port, debug=Old} ->
+ if
+ Old > 16, Level > 16 -> ok;
+ Old < 16, Level < 16 -> ok;
+ true ->
+ erlang:port_call(Port,?WXE_DEBUG_DRIVER, [Level bsr 4])
+ end,
+ put(?WXE_IDENTIFIER, Env#wx_env{debug=Level}),
+ wxe_server:set_debug(Server,Level),
+ ok
+ end.
+
+%% @spec () -> ok
+%% @doc Starts a wxErlang demo if examples directory exists and is compiled
+demo() ->
+ Priv = code:priv_dir(wx),
+ Demo = filename:join([filename:dirname(Priv),examples,demo]),
+ Mod = list_to_atom("demo"), %% Fool xref tests
+ case file:set_cwd(Demo) of
+ ok ->
+ apply(Mod, start, []);
+ _ ->
+ {error, no_demo_dir}
+ end.
+