kuuko pushed a commit to branch master.
commit 5a1180d1a084bdb8ace1a111e12729e0f5820998
Author: Kai Huuhko <[email protected]>
Date: Mon Apr 29 09:37:07 2013 +0000
Elementary: Initial support for copy & paste. selection_get/set/clear
works with Entry and has a test, the generic drop_cb is unfinished and
untested.
---
efl/elementary/cnp_callbacks.pxi | 37 ++++++---
efl/elementary/entry.pxd | 14 +++-
efl/elementary/entry.pyx | 20 +++++
efl/elementary/object.pxd | 15 ++--
efl/elementary/object.pyx | 172 ++++++++++++++++++++++-----------------
examples/elementary/test_cnp.py | 102 +++++++++++++++++++++++
6 files changed, 267 insertions(+), 93 deletions(-)
diff --git a/efl/elementary/cnp_callbacks.pxi b/efl/elementary/cnp_callbacks.pxi
index ba9a8a7..49e9750 100644
--- a/efl/elementary/cnp_callbacks.pxi
+++ b/efl/elementary/cnp_callbacks.pxi
@@ -1,7 +1,7 @@
-"""Structure holding the info about selected data.
-
-"""
cdef class SelectionData(object):
+
+ """Structure holding the info about selected data."""
+
cdef Elm_Selection_Data *sel_data
property x:
@@ -15,13 +15,13 @@ cdef class SelectionData(object):
return self.sel_data.y
property format:
- """:type: Elm_Selection_Format"""
+ """:type: :ref:`Elm_Selection_Format`"""
def __get__(self):
return self.sel_data.format
property data:
def __get__(self):
- # TODO
+ # TODO: void *
return None
property len:
@@ -32,7 +32,7 @@ cdef class SelectionData(object):
property action:
"""The action to perform with the data
- :type: Elm_Xdnd_Action
+ :type: :ref:`Elm_Xdnd_Action`
:since: 1.8
"""
@@ -40,23 +40,40 @@ cdef class SelectionData(object):
return self.sel_data.action
cdef Eina_Bool elm_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data
*ev):
- """Callback invoked in when the selected data is 'dropped' at its
destination.
+ """Callback invoked when the selected data is 'dropped' at its destination.
:param data: Application specific data
:param obj: The evas object where selected data is 'dropped'.
:param ev: struct holding information about selected data
"""
- pass
+ cdef:
+ SelectionData sd = SelectionData.__new__(SelectionData)
+ bint ret
+ sd.sel_data = ev
+
+ o = <object>data
+ cb_func = o.cnp_drop_cb
+ cb_data = o.cnp_drop_data
+
+ ret = cb_func(o, sd, cb_data)
+
+ sd.sel_data = NULL
+
+ return ret
cdef void elm_selection_loss_cb(void *data, Elm_Sel_Type selection):
- """Callback invoked in when the selection ownership for a given selection
is lost.
+ """Callback invoked when the selection ownership for a given selection is
lost.
:param data: Application specific data
:param selection: The selection that is lost
"""
- pass
+ o = <object>data
+ cb_func = o.cnp_selection_loss_cb
+ cb_data = o.cnp_selection_loss_data
+
+ cb_func(selection, cb_data)
cdef Evas_Object *elm_drag_icon_create_cb(void *data, Evas_Object *win,
Evas_Coord *xoff, Evas_Coord *yoff):
"""Callback called to create a drag icon object
diff --git a/efl/elementary/entry.pxd b/efl/elementary/entry.pxd
index 8188c8e..17ae521 100644
--- a/efl/elementary/entry.pxd
+++ b/efl/elementary/entry.pxd
@@ -3,7 +3,8 @@ from efl.evas cimport Eina_Bool, Eina_Rectangle, Evas_Object, \
from enums cimport Elm_Wrap_Type, Elm_Text_Format, Elm_Cnp_Mode, \
Elm_Scroller_Policy, Elm_Input_Panel_Layout, Elm_Input_Panel_Lang, \
Elm_Input_Panel_Lang, Elm_Input_Panel_Return_Key_Type, \
- Elm_Autocapital_Type, Elm_Icon_Type
+ Elm_Autocapital_Type, Elm_Icon_Type, Elm_Sel_Type, Elm_Sel_Format, \
+ Elm_Xdnd_Action
from libc.string cimport const_char
from libc.stdlib cimport const_void
@@ -25,6 +26,13 @@ cdef extern from "Elementary.h":
Eina_Bool hover_top
Eina_Bool hover_bottom
+ ctypedef struct Elm_Selection_Data:
+ Evas_Coord x, y
+ Elm_Sel_Format format
+ void *data
+ size_t len
+ Elm_Xdnd_Action action
+
ctypedef struct Elm_Entry_Context_Menu_Item:
pass
@@ -32,6 +40,8 @@ cdef extern from "Elementary.h":
ctypedef void (*Elm_Entry_Filter_Cb)(void *data, Evas_Object *entry, char
**text)
+ ctypedef Eina_Bool (*Elm_Drop_Cb) (void *data,
Evas_Object *obj, Elm_Selection_Data *ev)
+
# Data for the elm_entry_filter_limit_size() entry filter.
ctypedef struct Elm_Entry_Filter_Limit_Size:
int max_char_count # The maximum number of characters allowed.
@@ -139,3 +149,5 @@ cdef extern from "Elementary.h":
const_char *
elm_entry_context_menu_item_label_get(const_Elm_Entry_Context_Menu_Item *item)
void
elm_entry_context_menu_item_icon_get(const_Elm_Entry_Context_Menu_Item *item,
const_char **icon_file, const_char **icon_group, Elm_Icon_Type *icon_type)
+
+ Eina_Bool elm_cnp_selection_get(Evas_Object *obj,
Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
diff --git a/efl/elementary/entry.pyx b/efl/elementary/entry.pyx
index 80cadc0..7d0ede4 100644
--- a/efl/elementary/entry.pyx
+++ b/efl/elementary/entry.pyx
@@ -1925,6 +1925,26 @@ cdef class Entry(Object):
elm_entry_anchor_hover_end(self.obj)
+ # Copy and paste
+ def cnp_selection_get(self, selection, format):
+ """Retrieve data from a widget that has a selection.
+
+ Gets the current selection data from a widget.
+
+ .. seealso::
+
+ :py:func:`efl.elementary.object.Object.cnp_selection_get`
+
+ :param selection: Selection type for copying and pasting
+ :param format: Selection format
+
+ :raise RuntimeError: if getting cnp data fails.
+
+ """
+ if not elm_cnp_selection_get(self.obj, selection, format, NULL, NULL):
+ raise RuntimeError("Could not get cnp data from widget.")
+
+
def callback_changed_add(self, func, *args, **kwargs):
"""The text within the entry was changed."""
self._callback_add("changed", func, *args, **kwargs)
diff --git a/efl/elementary/object.pxd b/efl/elementary/object.pxd
index 104070a..308f321 100644
--- a/efl/elementary/object.pxd
+++ b/efl/elementary/object.pxd
@@ -152,10 +152,10 @@ cdef extern from "Elementary.h":
const_char * elm_object_translatable_text_get(Evas_Object *obj)
# TODO: CnP
- # Eina_Bool elm_cnp_selection_set(Evas_Object *obj,
Elm_Sel_Type selection, Elm_Sel_Format format, const_void *buf, size_t buflen)
- # Eina_Bool elm_cnp_selection_get(Evas_Object *obj,
Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
- # Eina_Bool elm_object_cnp_selection_clear(Evas_Object *obj,
Elm_Sel_Type selection)
- # void elm_cnp_selection_loss_callback_set(Evas_Object
*obj, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const_void *data)
+ Eina_Bool elm_cnp_selection_set(Evas_Object *obj,
Elm_Sel_Type selection, Elm_Sel_Format format, const_void *buf, size_t buflen)
+ Eina_Bool elm_cnp_selection_get(Evas_Object *obj,
Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
+ Eina_Bool elm_object_cnp_selection_clear(Evas_Object *obj,
Elm_Sel_Type selection)
+ void elm_cnp_selection_loss_callback_set(Evas_Object
*obj, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const_void *data)
# Eina_Bool elm_drop_target_add(Evas_Object *obj,
Elm_Sel_Format format, Elm_Drag_State entercb, void *enterdata, Elm_Drag_State
leavecb, void *leavedata, Elm_Drag_Pos poscb, void *posdata, Elm_Drop_Cb
dropcb, void *cbdata)
# Eina_Bool elm_drop_target_del(Evas_Object *obj)
# Eina_Bool elm_drag_start(Evas_Object *obj, Elm_Sel_Format
format, const_char *data, Elm_Xdnd_Action action, Elm_Drag_Icon_Create_Cb
createicon, void *createdata, Elm_Drag_Pos dragpos, void *dragdata,
Elm_Drag_Accept acceptcb, void *acceptdata, Elm_Drag_State dragdone, void
*donecbdata)
@@ -171,9 +171,10 @@ cdef class Canvas(evasCanvas):
pass
cdef class Object(evasObject):
- cdef object _elmcallbacks
- cdef object _elm_event_cbs
- cdef object _elm_signal_cbs
+ cdef:
+ object _elmcallbacks, _elm_event_cbs, _elm_signal_cbs
+ object cnp_drop_cb, cnp_drop_data
+ object cnp_selection_loss_cb, cnp_selection_loss_data
cpdef text_set(self, text)
cpdef text_get(self)
diff --git a/efl/elementary/object.pyx b/efl/elementary/object.pyx
index 4fa2ff9..8e3894f 100644
--- a/efl/elementary/object.pyx
+++ b/efl/elementary/object.pyx
@@ -22,9 +22,11 @@ Copy and Paste
--------------
Implements the following functionality
- a. select, copy/cut and paste
- b. clipboard
- c. drag and drop
+
+a. select, copy/cut and paste
+b. clipboard
+c. drag and drop
+
in order to share data across application windows.
Contains functions to select text or a portion of data,
@@ -46,11 +48,13 @@ Clipboard selection is for explicit copying behavior
Thus, in applications most cases only use the clipboard selection.
As stated before, taking ownership of a selection doesn't move any actual data.
Copying and Pasting is described as follows:
- 1. Copy text in Program A : Program A takes ownership of the selection
- 2. Paste text in Program B : Program B notes that Program A owns the selection
- 3. Program B asks A for the text
- 4. Program A responds and sends the text to program B
- 5. Program B pastes the response
+
+1. Copy text in Program A : Program A takes ownership of the selection
+2. Paste text in Program B : Program B notes that Program A owns the selection
+3. Program B asks A for the text
+4. Program A responds and sends the text to program B
+5. Program B pastes the response
+
More information is on
- http://www.jwz.org/doc/x-cut-and-paste.html
- X11R6 Inter-Client Communication Conventions Manual, section 2
@@ -79,7 +83,8 @@ Selection type
==============
Defines the types of selection property names.
-:see: `http://www.x.org/docs/X11/xlib.pdf`_ for more details.
+
+:see: http://www.x.org/docs/X11/xlib.pdf for more details.
.. data:: ELM_SEL_TYPE_PRIMARY
@@ -140,6 +145,7 @@ XDND action
===========
Defines the kind of action associated with the drop data if for XDND
+
:since: 1.8
.. data:: ELM_XDND_ACTION_UNKNOWN
@@ -156,7 +162,7 @@ Defines the kind of action associated with the drop data if
for XDND
.. data:: ELM_XDND_ACTION_PRIVATE
- Pricate action type
+ Private action type
.. data:: ELM_XDND_ACTION_ASK
@@ -177,7 +183,8 @@ Defines the kind of action associated with the drop data if
for XDND
"""
-from cpython cimport PyObject, Py_INCREF, Py_DECREF, PyObject_GetAttr
+from cpython cimport PyObject, Py_INCREF, Py_DECREF, PyObject_GetAttr, \
+ PyObject_GetBuffer, PyBuffer_Release, PyBUF_SIMPLE, PyObject_CheckBuffer
include "widget_header.pxi"
include "tooltips.pxi"
@@ -243,7 +250,7 @@ cdef void _object_callback(void *data,
else:
ei = event_conv(<long>event_info)
func(obj, ei, *args, **kargs)
- except Exception, e:
+ except:
traceback.print_exc()
cdef bint _event_dispatcher(Object obj, Object src, Evas_Callback_Type t,
event_info):
@@ -252,7 +259,7 @@ cdef bint _event_dispatcher(Object obj, Object src,
Evas_Callback_Type t, event_
for func, args, kargs in obj._elm_event_cbs:
try:
ret = func(obj, src, t, event_info, *args, **kargs)
- except Exception, e:
+ except:
traceback.print_exc()
else:
return ret
@@ -292,10 +299,10 @@ cdef void signal_callback(void *data, Evas_Object *obj,
for func, args, kargs in lst:
try:
func(self, _ctouni(emission), _ctouni(source), *args, **kargs)
- except Exception, e:
+ except:
traceback.print_exc()
-# TODO: include "cnp_callbacks.pxi"
+include "cnp_callbacks.pxi"
# TODO: Is this handled in Eo now?
cdef void _event_data_del_cb(void *data, Evas_Object *o, void *event_info)
with gil:
@@ -587,6 +594,7 @@ cdef class Object(evasObject):
:type: string
"""
+ # FIXME: Now that we have Eo, is this useful anymore?
def __get__(self):
return elm_object_widget_type_get(self.obj)
@@ -1588,83 +1596,97 @@ cdef class Object(evasObject):
"""
return <long>self.obj
- # TODO: Copy and Paste
- # def cnp_selection_set(self, Elm_Sel_Type selection, Elm_Sel_Format
format, buf, buflen):
- # """Set copy data for a widget.
-
- # Set copy data and take ownership of selection. Format is used for
specifying the selection type,
- # and this is used during pasting.
-
- # :param selection: Selection type for copying and pasting
- # :param format: Selection format
- # :param buf: The data selected
- # :param buflen: The size of @p buf
- # :raise RuntimeError: if setting cnp data fails.
-
- # """
- # if not elm_cnp_selection_set(self.obj, selection, format, const_void
*buf, size_t buflen):
- # raise RuntimeError("Could not set cnp data for widget.")
-
- # def cnp_selection_get(self, selection, format, datacb, udata):
- # """Retrieve data from a widget that has a selection.
+ # Copy and Paste
+ def cnp_selection_set(self, Elm_Sel_Type selection, Elm_Sel_Format format,
buf):
+ """Set copy data for a widget.
- # Gets the current selection data from a widget.
- # The widget input here will usually be elm_entry,
- # in which case @p datacb and @p udata can be NULL.
- # If a different widget is passed, @p datacb and @p udata are used for
retrieving data.
+ Set copy data and take ownership of selection. Format is used for
specifying the selection type,
+ and this is used during pasting.
- # @see also elm_cnp_selection_set()
+ :param selection: Selection type for copying and pasting
+ :type selection: :ref:`Elm_Sel_Type`
+ :param format: Selection format
+ :type format: :ref:`Elm_Sel_Format`
+ :param buf: The data selected
+ :type buf: An object that supports the new buffer interface
- # :param selection: Selection type for copying and pasting
- # :param format: Selection format
- # :param datacb: The user data callback if the target widget isn't
elm_entry
- # :param udata: The user data pointer for @p datacb
- # :raise RuntimeError: if getting cnp data fails.
+ :raise RuntimeError: if setting cnp data fails.
- # """
- # if not elm_cnp_selection_get(self.obj, selection, format,
Elm_Drop_Cb datacb, void *udata):
- # raise RuntimeError("Could not get cnp data from widget.")
-
- # def cnp_selection_clear(self, Elm_Sel_Type selection):
- # """Clear the selection data of a widget.
+ """
+ cdef Py_buffer view
+ if isinstance(buf, unicode): buf = PyUnicode_AsUTF8String(buf)
+ if not PyObject_CheckBuffer(buf):
+ raise TypeError("The provided object does not support buffer
interface.")
+ PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE)
+ if not elm_cnp_selection_set(self.obj, selection, format, <const_void
*>view.buf, view.itemsize):
+ raise RuntimeError("Could not set cnp data for widget.")
+ PyBuffer_Release(&view)
+
+ def cnp_selection_get(self, selection, format, datacb, udata = None):
+ """Retrieve data from a widget that has a selection.
+
+ Gets the current selection data from a widget.
+ The widget input here will usually be elm_entry,
+ in which case @p datacb and @p udata can be NULL.
+ If a different widget is passed, @p datacb and @p udata are used for
retrieving data.
+
+ :param selection: Selection type for copying and pasting
+ :param format: Selection format
+ :param datacb: The user data callback if the target widget isn't
elm_entry
+ :param udata: The user data pointer for @p datacb
+
+ :raise RuntimeError: if getting cnp data fails.
- # Clear all data from the selection which is owned by a widget.
+ """
+ if not callable(datacb):
+ raise TypeError("datacb is not callable.")
+ self.cnp_drop_cb = datacb
+ self.cnp_drop_data = udata
+ if not elm_cnp_selection_get(self.obj, selection, format, elm_drop_cb,
<void *>self):
+ raise RuntimeError("Could not get cnp data from widget.")
- # @see also elm_cnp_selection_set()
+ def cnp_selection_clear(self, Elm_Sel_Type selection):
+ """Clear the selection data of a widget.
- # :param selection: Selection type for copying and pasting
- # :raise RuntimeError: if clearing cnp data fails.
+ Clear all data from the selection which is owned by a widget.
- # """
- # if not elm_object_cnp_selection_clear(self.obj, selection):
- # raise RuntimeError("Could not clear cnp data from widget.")
+ :param selection: Selection type for copying and pasting
+ :type selection: :ref:`Elm_Sel_Type`
+ :raise RuntimeError: if clearing cnp data fails.
- # def cnp_selection_loss_callback_set(self, Elm_Sel_Type selection, func,
data):
- # """Set a function to be called when a selection is lost
+ """
+ if not elm_object_cnp_selection_clear(self.obj, selection):
+ raise RuntimeError("Could not clear cnp data from widget.")
- # The function @p func is set of be called when selection @p selection
is lost
- # to another process or when elm_cnp_selection_set() is called. If @p
func
- # is NULL then it is not called. @p data is passed as the data
parameter to
- # the callback functions and selection is passed in as the selection
that
- # has been lost.
+ def cnp_selection_loss_callback_set(self, Elm_Sel_Type selection, func,
data = None):
+ """Set a function to be called when a selection is lost
- # elm_cnp_selection_set() and elm_object_cnp_selection_clear()
automatically
- # set this los callback to NULL when called. If you wish to take the
selection
- # and then be notified of loss please do this (for example)::
+ The function @p func is set of be called when selection @p selection
is lost
+ to another process or when elm_cnp_selection_set() is called. If @p
func
+ is NULL then it is not called. @p data is passed as the data parameter
to
+ the callback functions and selection is passed in as the selection that
+ has been lost.
- # elm_cnp_selection_set(obj, ELM_SEL_TYPE_PRIMARY,
ELM_SEL_FORMAT_TEXT, "hello", strlen(hello));
- # elm_cnp_selection_loss_callback_set(obj, ELM_SEL_TYPE_PRIMARY,
loss_cb, NULL);
+ elm_cnp_selection_set() and elm_object_cnp_selection_clear()
automatically
+ set this loss callback to NULL when called. If you wish to take the
selection
+ and then be notified of loss please do this (for example)::
- # @see also elm_cnp_selection_set()
+ obj.cnp_selection_set(ELM_SEL_TYPE_PRIMARY, ELM_SEL_FORMAT_TEXT,
"hello")
+ obj.cnp_selection_loss_callback_set(ELM_SEL_TYPE_PRIMARY, loss_cb)
- # :param selection: Selection to be notified of for loss
- # :param func: The function to call
- # :param data: The data pointer passed to the function.
+ :param selection: Selection to be notified of for loss
+ :param func: The function to call
+ :param data: The data pointer passed to the function.
- # """
- # elm_cnp_selection_loss_callback_set(self.obj, selection,
Elm_Selection_Loss_Cb func, const void *data)
+ """
+ if not callable(func):
+ raise TypeError("func is not callable.")
+ self.cnp_selection_loss_cb = func
+ self.cnp_selection_loss_data = data
+ elm_cnp_selection_loss_callback_set(self.obj, selection,
elm_selection_loss_cb, <const_void *>data)
+ # TODO:
# def drop_target_add(self, Elm_Sel_Format format, entercb, enterdata,
leavecb, leavedata, poscb, posdata, dropcb, dropdata):
# """Set the given object as a target for drops for drag-and-drop
diff --git a/examples/elementary/test_cnp.py b/examples/elementary/test_cnp.py
new file mode 100644
index 0000000..f2cff97
--- /dev/null
+++ b/examples/elementary/test_cnp.py
@@ -0,0 +1,102 @@
+from efl import elementary
+from efl.evas import EVAS_HINT_FILL, EVAS_HINT_EXPAND
+
+from efl.elementary.window import StandardWindow
+from efl.elementary.label import Label
+from efl.elementary.entry import Entry, ELM_WRAP_CHAR
+from efl.elementary.grid import Grid
+from efl.elementary.button import Button
+from efl.elementary.object import ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT
+
+def bt_copy_clicked(obj, data):
+ en = data
+ txt = en.text
+
+ glb.text = txt
+ en.parent_widget.cnp_selection_set(ELM_SEL_TYPE_CLIPBOARD, \
+ ELM_SEL_FORMAT_TEXT, txt)
+
+def bt_paste_clicked(obj, data):
+ en = data
+
+ en.cnp_selection_get(ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT)
+
+def bt_clear_clicked(obj, data):
+ en = data
+
+ glb.text = ""
+ en.parent_widget.cnp_selection_clear(ELM_SEL_TYPE_CLIPBOARD)
+
+def cnp_clicked(obj):
+ win = StandardWindow("copypaste", "CopyPaste")
+ win.autodel = True
+ if obj is None:
+ win.callback_delete_request_add(lambda o: elementary.exit())
+
+ gd = Grid(win)
+ gd.size = 100, 100
+ gd.size_hint_weight = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
+ win.resize_object_add(gd)
+ gd.show()
+
+ en = Entry(win)
+ en.scrollable = True
+ en.line_wrap = ELM_WRAP_CHAR
+ en.size_hint_weight = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
+ en.size_hint_align = EVAS_HINT_FILL, EVAS_HINT_FILL
+ en.text = "Elementary provides "
+ gd.pack(en, 10, 10, 60, 30)
+ en.show()
+
+ bt = Button(win)
+ bt.text = "Copy from left entry"
+ bt.callback_clicked_add(bt_copy_clicked, en)
+ gd.pack(bt, 70, 10, 22, 30)
+ bt.show()
+
+ bt = Button(win)
+ bt.text = "Clear clipboard"
+ bt.callback_clicked_add(bt_clear_clicked, en)
+ gd.pack(bt, 70, 70, 22, 20)
+ bt.show()
+
+ en = Entry(win)
+ en.scrollable = True
+ en.line_wrap = ELM_WRAP_CHAR
+ en.size_hint_weight = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
+ en.size_hint_align = EVAS_HINT_FILL, EVAS_HINT_FILL
+ en.text = "rich copying and pasting functionality,"
+ gd.pack(en, 10, 40, 60, 30)
+ en.show()
+
+ bt = Button(win)
+ bt.text = "Paste to left entry"
+ bt.callback_clicked_add(bt_paste_clicked, en)
+ gd.pack(bt, 70, 40, 22, 30)
+ bt.show()
+
+ lb = Label(win)
+ lb.text = "<b>Clipboard:</b>"
+ lb.size_hint_weight = 0.0, 0.0
+ lb.size_hint_align = EVAS_HINT_FILL, EVAS_HINT_FILL
+ gd.pack(lb, 10, 70, 60, 10)
+ lb.show()
+
+ global glb
+ glb = Label(win)
+ glb.text = ""
+ glb.size_hint_weight = 0.0, 0.0
+ glb.size_hint_align = EVAS_HINT_FILL, EVAS_HINT_FILL
+ gd.pack(glb, 10, 80, 60, 10)
+ glb.show()
+
+ win.size = 480, 200
+ win.show()
+
+if __name__ == "__main__":
+ elementary.init()
+
+ cnp_clicked(None)
+
+ elementary.run()
+ elementary.shutdown()
--
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1