2 changed files with 698 additions and 0 deletions
Unified View
Diff Options
@ -0,0 +1,273 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# -*- coding: UTF-8 -*- |
||||
|
|
||||
|
"""Contains test cases for the widgets.py module.""" |
||||
|
|
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
import sys |
||||
|
import os.path |
||||
|
import unittest |
||||
|
|
||||
|
PATH = os.path.realpath(os.path.abspath(__file__)) |
||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(PATH))) |
||||
|
|
||||
|
|
||||
|
try: |
||||
|
import wx |
||||
|
import mock |
||||
|
|
||||
|
from youtube_dl_gui.widgets import ( |
||||
|
ListBoxWithHeaders, |
||||
|
CustomComboBox, |
||||
|
ListBoxPopup |
||||
|
) |
||||
|
except ImportError as error: |
||||
|
print error |
||||
|
sys.exit(1) |
||||
|
|
||||
|
|
||||
|
class TestListBoxWithHeaders(unittest.TestCase): |
||||
|
|
||||
|
"""Test cases for the ListBoxWithHeaders widget.""" |
||||
|
|
||||
|
def setUp(self): |
||||
|
self.app = wx.App() |
||||
|
|
||||
|
self.frame = wx.Frame(None) |
||||
|
self.listbox = ListBoxWithHeaders(self.frame) |
||||
|
|
||||
|
self.listbox.add_header("Header") |
||||
|
self.listbox.add_items(["item%s" % i for i in xrange(10)]) |
||||
|
|
||||
|
def tearDown(self): |
||||
|
self.frame.Destroy() |
||||
|
|
||||
|
def test_find_string_header_found(self): |
||||
|
self.assertEqual(self.listbox.FindString("Header"), 0) |
||||
|
|
||||
|
def test_find_string_header_not_found(self): |
||||
|
self.assertEqual(self.listbox.FindString("Header2"), wx.NOT_FOUND) |
||||
|
|
||||
|
def test_find_string_item_found(self): |
||||
|
self.assertEqual(self.listbox.FindString("item1"), 2) |
||||
|
|
||||
|
def test_find_string_item_not_found(self): |
||||
|
self.assertEqual(self.listbox.FindString("item"), wx.NOT_FOUND) |
||||
|
|
||||
|
def test_get_string_header(self): |
||||
|
self.assertEqual(self.listbox.GetString(0), "Header") |
||||
|
|
||||
|
def test_get_string_item(self): |
||||
|
self.assertEqual(self.listbox.GetString(10), "item9") |
||||
|
|
||||
|
def test_get_string_item_not_found(self): |
||||
|
self.assertEqual(self.listbox.GetString(11), "") |
||||
|
|
||||
|
def test_get_string_item_negative_index(self): |
||||
|
self.assertEqual(self.listbox.GetString(-1), "") |
||||
|
|
||||
|
def test_insert_items(self): |
||||
|
self.listbox.SetSelection(1) |
||||
|
|
||||
|
self.listbox.InsertItems(["new_item1", "new_item2"], 1) |
||||
|
self.assertEqual(self.listbox.GetString(1), "new_item1") |
||||
|
self.assertEqual(self.listbox.GetString(2), "new_item2") |
||||
|
self.assertEqual(self.listbox.GetString(3), "item0") |
||||
|
|
||||
|
self.assertTrue(self.listbox.IsSelected(3)) # Old selection + 2 |
||||
|
|
||||
|
def test_set_selection_header(self): |
||||
|
self.listbox.SetSelection(0) |
||||
|
self.assertFalse(self.listbox.IsSelected(0)) |
||||
|
|
||||
|
def test_set_selection_item_valid_index(self): |
||||
|
self.listbox.SetSelection(1) |
||||
|
self.assertEqual(self.listbox.GetSelection(), 1) |
||||
|
|
||||
|
def test_set_selection_item_invalid_index(self): |
||||
|
self.listbox.SetSelection(1) |
||||
|
self.assertEqual(self.listbox.GetSelection(), 1) |
||||
|
|
||||
|
self.listbox.SetSelection(wx.NOT_FOUND) |
||||
|
self.assertEqual(self.listbox.GetSelection(), wx.NOT_FOUND) |
||||
|
|
||||
|
def test_set_string_item(self): |
||||
|
self.listbox.SetString(1, "item_mod0") |
||||
|
self.assertEqual(self.listbox.GetString(1), "item_mod0") |
||||
|
|
||||
|
def test_set_string_header(self): |
||||
|
self.listbox.SetString(0, "New header") |
||||
|
self.assertEqual(self.listbox.GetString(0), "New header") |
||||
|
|
||||
|
# Make sure that the header is not selectable |
||||
|
self.listbox.SetSelection(0) |
||||
|
self.assertFalse(self.listbox.IsSelected(0)) |
||||
|
|
||||
|
def test_set_string_selection_header(self): |
||||
|
self.assertFalse(self.listbox.SetStringSelection("Header")) |
||||
|
self.assertFalse(self.listbox.IsSelected(0)) |
||||
|
|
||||
|
def test_set_string_selection_item(self): |
||||
|
self.assertTrue(self.listbox.SetStringSelection("item1")) |
||||
|
self.assertTrue(self.listbox.IsSelected(2)) |
||||
|
|
||||
|
def test_get_string_selection(self): |
||||
|
self.listbox.SetSelection(1) |
||||
|
self.assertEqual(self.listbox.GetStringSelection(), "item0") |
||||
|
|
||||
|
def test_get_string_selection_empty(self): |
||||
|
self.assertEqual(self.listbox.GetStringSelection(), "") |
||||
|
|
||||
|
# wx.ItemContainer methods |
||||
|
|
||||
|
def test_append(self): |
||||
|
self.listbox.Append("item666") |
||||
|
self.assertEqual(self.listbox.GetString(11), "item666") |
||||
|
|
||||
|
def test_append_items(self): |
||||
|
self.listbox.AppendItems(["new_item1", "new_item2"]) |
||||
|
self.assertEqual(self.listbox.GetString(11), "new_item1") |
||||
|
self.assertEqual(self.listbox.GetString(12), "new_item2") |
||||
|
|
||||
|
def test_clear(self): |
||||
|
self.listbox.Clear() |
||||
|
self.assertEqual(self.listbox.GetItems(), []) |
||||
|
|
||||
|
def test_delete(self): |
||||
|
self.listbox.Delete(0) |
||||
|
self.assertEqual(self.listbox.GetString(0), "item0") |
||||
|
|
||||
|
# Test item selection |
||||
|
self.listbox.SetSelection(0) |
||||
|
self.assertTrue(self.listbox.IsSelected(0)) |
||||
|
|
||||
|
# Test object extra methods |
||||
|
|
||||
|
def test_add_header(self): |
||||
|
self.listbox.add_header("Header2") |
||||
|
self.listbox.SetSelection(11) |
||||
|
self.assertFalse(self.listbox.IsSelected(11)) |
||||
|
|
||||
|
@mock.patch("wx.ListBox.Append") |
||||
|
def test_add_item_with_prefix(self, mock_append): |
||||
|
self.listbox.add_item("new_item") |
||||
|
mock_append.assert_called_once_with(ListBoxWithHeaders.TEXT_PREFIX + "new_item") |
||||
|
|
||||
|
@mock.patch("wx.ListBox.Append") |
||||
|
def test_add_item_without_prefix(self, mock_append): |
||||
|
self.listbox.add_item("new_item", with_prefix=False) |
||||
|
mock_append.assert_called_once_with("new_item") |
||||
|
|
||||
|
@mock.patch("wx.ListBox.AppendItems") |
||||
|
def test_add_items_with_prefix(self, mock_append): |
||||
|
self.listbox.add_items(["new_item1", "new_item2"]) |
||||
|
mock_append.assert_called_once_with([ListBoxWithHeaders.TEXT_PREFIX + "new_item1", |
||||
|
ListBoxWithHeaders.TEXT_PREFIX + "new_item2"]) |
||||
|
@mock.patch("wx.ListBox.AppendItems") |
||||
|
def test_add_items_without_prefix(self, mock_append): |
||||
|
self.listbox.add_items(["new_item1", "new_item2"], with_prefix=False) |
||||
|
mock_append.assert_called_once_with(["new_item1", "new_item2"]) |
||||
|
|
||||
|
|
||||
|
class TestCustomComboBox(unittest.TestCase): |
||||
|
|
||||
|
"""Test cases for the CustomComboBox widget.""" |
||||
|
|
||||
|
def setUp(self): |
||||
|
self.app = wx.App() |
||||
|
|
||||
|
self.frame = wx.Frame(None) |
||||
|
self.combobox = CustomComboBox(self.frame) |
||||
|
|
||||
|
# Call directly the ListBoxWithHeaders methods |
||||
|
self.combobox.listbox.GetControl().add_header("Header") |
||||
|
self.combobox.listbox.GetControl().add_items(["item%s" % i for i in xrange(10)]) |
||||
|
|
||||
|
def tearDown(self): |
||||
|
self.frame.Destroy() |
||||
|
|
||||
|
def test_init(self): |
||||
|
combobox = CustomComboBox(self.frame, -1, "item1", choices=["item0", "item1", "item2"]) |
||||
|
|
||||
|
self.assertEqual(combobox.GetValue(), "item1") |
||||
|
self.assertEqual(combobox.GetCount(), 3) |
||||
|
self.assertEqual(combobox.GetSelection(), 1) |
||||
|
|
||||
|
# wx.ComboBox methods |
||||
|
# Not all of them since most of them are calls to ListBoxWithHeaders |
||||
|
# methods and we already have tests for those |
||||
|
|
||||
|
def test_is_list_empty_false(self): |
||||
|
self.assertFalse(self.combobox.IsListEmpty()) |
||||
|
|
||||
|
def test_is_list_empty_true(self): |
||||
|
self.combobox.Clear() |
||||
|
self.assertTrue(self.combobox.IsListEmpty()) |
||||
|
|
||||
|
def test_is_text_empty_false(self): |
||||
|
self.combobox.SetValue("somevalue") |
||||
|
self.assertFalse(self.combobox.IsTextEmpty()) |
||||
|
|
||||
|
def test_is_text_empty_true(self): |
||||
|
self.assertTrue(self.combobox.IsTextEmpty()) |
||||
|
|
||||
|
def test_set_selection_item(self): |
||||
|
self.combobox.SetSelection(1) |
||||
|
self.assertEqual(self.combobox.GetSelection(), 1) |
||||
|
self.assertEqual(self.combobox.GetValue(), "item0") |
||||
|
|
||||
|
def test_set_selection_header(self): |
||||
|
self.combobox.SetSelection(0) |
||||
|
self.assertEqual(self.combobox.GetSelection(), wx.NOT_FOUND) |
||||
|
self.assertEqual(self.combobox.GetValue(), "") |
||||
|
|
||||
|
def test_set_string_selection_item(self): |
||||
|
self.combobox.SetStringSelection("item0") |
||||
|
self.assertEqual(self.combobox.GetStringSelection(), "item0") |
||||
|
self.assertEqual(self.combobox.GetValue(), "item0") |
||||
|
|
||||
|
def test_set_string_selection_header(self): |
||||
|
self.combobox.SetStringSelection("Header") |
||||
|
self.assertEqual(self.combobox.GetStringSelection(), "") |
||||
|
self.assertEqual(self.combobox.GetValue(), "") |
||||
|
|
||||
|
def test_set_string_selection_invalid_string(self): |
||||
|
self.combobox.SetStringSelection("abcde") |
||||
|
self.assertEqual(self.combobox.GetStringSelection(), "") |
||||
|
self.assertEqual(self.combobox.GetValue(), "") |
||||
|
|
||||
|
# wx.ItemContainer methods |
||||
|
|
||||
|
def test_clear(self): |
||||
|
self.combobox.SetValue("value") |
||||
|
|
||||
|
self.combobox.Clear() |
||||
|
self.assertEqual(self.combobox.GetCount(), 0) |
||||
|
self.assertTrue(self.combobox.IsTextEmpty()) |
||||
|
|
||||
|
def test_append(self): |
||||
|
self.combobox.Append("item10") |
||||
|
self.assertEqual(self.combobox.GetCount(), 12) |
||||
|
|
||||
|
def test_append_items(self): |
||||
|
self.combobox.AppendItems(["item10", "item11"]) |
||||
|
self.assertEqual(self.combobox.GetCount(), 13) |
||||
|
|
||||
|
def test_delete(self): |
||||
|
self.combobox.Delete(1) |
||||
|
self.assertEqual(self.combobox.GetString(1), "item1") |
||||
|
|
||||
|
# wx.TextEntry methods |
||||
|
|
||||
|
def test_get_value(self): |
||||
|
self.combobox.SetValue("value") |
||||
|
self.assertEqual(self.combobox.GetValue(), "value") |
||||
|
|
||||
|
|
||||
|
def main(): |
||||
|
unittest.main() |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
main() |
@ -0,0 +1,425 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# -*- coding: UTF-8 -*- |
||||
|
|
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
import sys |
||||
|
|
||||
|
try: |
||||
|
import wx |
||||
|
except ImportError as error: |
||||
|
print error |
||||
|
sys.exit(1) |
||||
|
|
||||
|
|
||||
|
def crt_command_event(event_type, event_id=0): |
||||
|
"""Shortcut to create command events.""" |
||||
|
return wx.CommandEvent(event_type.typeId, event_id) |
||||
|
|
||||
|
|
||||
|
class ListBoxWithHeaders(wx.ListBox): |
||||
|
|
||||
|
"""Custom ListBox object that supports 'headers'. |
||||
|
|
||||
|
Attributes: |
||||
|
NAME (string): Default name for the name argument of the __init__. |
||||
|
|
||||
|
TEXT_PREFIX (string): Text to add before normal items in order to |
||||
|
distinguish them (normal items) from headers. |
||||
|
|
||||
|
EVENTS (list): List with events to overwrite to avoid header selection. |
||||
|
|
||||
|
""" |
||||
|
|
||||
|
NAME = "listBoxWithHeaders" |
||||
|
|
||||
|
TEXT_PREFIX = " " |
||||
|
|
||||
|
EVENTS = [ |
||||
|
wx.EVT_LEFT_DOWN, |
||||
|
wx.EVT_LEFT_DCLICK, |
||||
|
wx.EVT_RIGHT_DOWN, |
||||
|
wx.EVT_RIGHT_DCLICK, |
||||
|
wx.EVT_MIDDLE_DOWN, |
||||
|
wx.EVT_MIDDLE_DCLICK |
||||
|
] |
||||
|
|
||||
|
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, |
||||
|
size=wx.DefaultSize, choices=[], style=0, validator=wx.DefaultValidator, name=NAME): |
||||
|
super(ListBoxWithHeaders, self).__init__(parent, id, pos, size, [], style, validator, name) |
||||
|
self.__headers = set() |
||||
|
|
||||
|
# Ignore all key events i'm bored to handle the header selection |
||||
|
self.Bind(wx.EVT_KEY_DOWN, lambda event: None) |
||||
|
|
||||
|
# Make sure that a header is never selected |
||||
|
self.Bind(wx.EVT_LISTBOX, self._on_listbox) |
||||
|
for event in self.EVENTS: |
||||
|
self.Bind(event, self._disable_header_selection) |
||||
|
|
||||
|
# Append the items in our own way in order to add the TEXT_PREFIX |
||||
|
self.AppendItems(choices) |
||||
|
|
||||
|
def _disable_header_selection(self, event): |
||||
|
"""Stop event propagation if the selected item is a header.""" |
||||
|
row = self.HitTest(event.GetPosition()) |
||||
|
event_skip = True |
||||
|
|
||||
|
if row != wx.NOT_FOUND and self.GetString(row) in self.__headers: |
||||
|
event_skip = False |
||||
|
|
||||
|
event.Skip(event_skip) |
||||
|
|
||||
|
def _on_listbox(self, event): |
||||
|
"""Make sure no header is selected.""" |
||||
|
if event.GetString() in self.__headers: |
||||
|
self.Deselect(event.GetSelection()) |
||||
|
event.Skip() |
||||
|
|
||||
|
def _add_prefix(self, string): |
||||
|
return self.TEXT_PREFIX + string |
||||
|
|
||||
|
def _remove_prefix(self, string): |
||||
|
if string[:len(self.TEXT_PREFIX)] == self.TEXT_PREFIX: |
||||
|
return string[len(self.TEXT_PREFIX):] |
||||
|
return string |
||||
|
|
||||
|
# wx.ListBox methods |
||||
|
|
||||
|
def FindString(self, string): |
||||
|
index = super(ListBoxWithHeaders, self).FindString(string) |
||||
|
|
||||
|
if index == wx.NOT_FOUND: |
||||
|
# This time try with prefix |
||||
|
index = super(ListBoxWithHeaders, self).FindString(self._add_prefix(string)) |
||||
|
|
||||
|
return index |
||||
|
|
||||
|
def GetStringSelection(self): |
||||
|
return self._remove_prefix(super(ListBoxWithHeaders, self).GetStringSelection()) |
||||
|
|
||||
|
def GetString(self, index): |
||||
|
if index < 0 or index >= self.GetCount(): |
||||
|
# Return empty string based on the wx.ListBox docs |
||||
|
# for some reason parent GetString does not handle |
||||
|
# invalid indices |
||||
|
return "" |
||||
|
|
||||
|
return self._remove_prefix(super(ListBoxWithHeaders, self).GetString(index)) |
||||
|
|
||||
|
def InsertItems(self, items, pos): |
||||
|
items = [self._add_prefix(item) for item in items] |
||||
|
super(ListBoxWithHeaders, self).InsertItems(items, pos) |
||||
|
|
||||
|
def SetSelection(self, index): |
||||
|
if index == wx.NOT_FOUND: |
||||
|
self.Deselect(self.GetSelection()) |
||||
|
elif self.GetString(index) not in self.__headers: |
||||
|
super(ListBoxWithHeaders, self).SetSelection(index) |
||||
|
|
||||
|
def SetString(self, index, string): |
||||
|
old_string = self.GetString(index) |
||||
|
|
||||
|
if old_string in self.__headers and string != old_string: |
||||
|
self.__headers.remove(old_string) |
||||
|
self.__headers.add(string) |
||||
|
|
||||
|
super(ListBoxWithHeaders, self).SetString(index, string) |
||||
|
|
||||
|
def SetStringSelection(self, string): |
||||
|
if string in self.__headers: |
||||
|
return False |
||||
|
|
||||
|
self.SetSelection(self.FindString(string)) |
||||
|
return True |
||||
|
|
||||
|
# wx.ItemContainer methods |
||||
|
|
||||
|
def Append(self, string): |
||||
|
super(ListBoxWithHeaders, self).Append(self._add_prefix(string)) |
||||
|
|
||||
|
def AppendItems(self, strings): |
||||
|
strings = [self._add_prefix(string) for string in strings] |
||||
|
super(ListBoxWithHeaders, self).AppendItems(strings) |
||||
|
|
||||
|
def Clear(self): |
||||
|
self.__headers.clear() |
||||
|
super(ListBoxWithHeaders, self).Clear() |
||||
|
|
||||
|
def Delete(self, index): |
||||
|
string = self.GetString(index) |
||||
|
|
||||
|
if string in self.__headers: |
||||
|
self.__headers.remove(string) |
||||
|
|
||||
|
super(ListBoxWithHeaders, self).Delete(index) |
||||
|
|
||||
|
# Extra methods |
||||
|
|
||||
|
def add_header(self, header_string): |
||||
|
self.__headers.add(header_string) |
||||
|
super(ListBoxWithHeaders, self).Append(header_string) |
||||
|
|
||||
|
def add_item(self, item, with_prefix=True): |
||||
|
if with_prefix: |
||||
|
item = self._add_prefix(item) |
||||
|
|
||||
|
super(ListBoxWithHeaders, self).Append(item) |
||||
|
|
||||
|
def add_items(self, items, with_prefix=True): |
||||
|
if with_prefix: |
||||
|
items = [self._add_prefix(item) for item in items] |
||||
|
|
||||
|
super(ListBoxWithHeaders, self).AppendItems(items) |
||||
|
|
||||
|
|
||||
|
class ListBoxPopup(wx.PopupTransientWindow): |
||||
|
|
||||
|
"""ListBoxWithHeaders as a popup. |
||||
|
|
||||
|
This class uses the wx.PopupTransientWindow to create the popup and the |
||||
|
API is based on the wx.combo.ComboPopup class. |
||||
|
|
||||
|
Attributes: |
||||
|
EVENTS_TABLE (dict): Dictionary that contains all the events |
||||
|
that this class emits. |
||||
|
|
||||
|
""" |
||||
|
|
||||
|
EVENTS_TABLE = { |
||||
|
"EVT_COMBOBOX": crt_command_event(wx.EVT_COMBOBOX), |
||||
|
"EVT_COMBOBOX_DROPDOWN" : crt_command_event(wx.EVT_COMBOBOX_DROPDOWN), |
||||
|
"EVT_COMBOBOX_CLOSEUP": crt_command_event(wx.EVT_COMBOBOX_CLOSEUP) |
||||
|
} |
||||
|
|
||||
|
def __init__(self): |
||||
|
super(ListBoxPopup, self).__init__(None) |
||||
|
self.__listbox = None |
||||
|
|
||||
|
def _on_motion(self, event): |
||||
|
row = self.__listbox.HitTest(event.GetPosition()) |
||||
|
|
||||
|
if row != wx.NOT_FOUND: |
||||
|
self.__listbox.SetSelection(row) |
||||
|
|
||||
|
if self.__listbox.IsSelected(row): |
||||
|
self.curitem = row |
||||
|
|
||||
|
def _on_left_down(self, event): |
||||
|
self.value = self.curitem |
||||
|
self.Dismiss() |
||||
|
|
||||
|
# Send EVT_COMBOBOX to inform the parent for changes |
||||
|
wx.PostEvent(self, self.EVENTS_TABLE["EVT_COMBOBOX"]) |
||||
|
|
||||
|
def Popup(self): |
||||
|
super(ListBoxPopup, self).Popup() |
||||
|
wx.PostEvent(self, self.EVENTS_TABLE["EVT_COMBOBOX_DROPDOWN"]) |
||||
|
|
||||
|
def OnDismiss(self): |
||||
|
wx.PostEvent(self, self.EVENTS_TABLE["EVT_COMBOBOX_CLOSEUP"]) |
||||
|
|
||||
|
# wx.combo.ComboPopup methods |
||||
|
|
||||
|
def Init(self): |
||||
|
self.value = self.curitem = -1 |
||||
|
|
||||
|
def Create(self, parent): |
||||
|
self.__listbox = ListBoxWithHeaders(parent, style=wx.LB_SINGLE) |
||||
|
|
||||
|
self.__listbox.Bind(wx.EVT_MOTION, self._on_motion) |
||||
|
self.__listbox.Bind(wx.EVT_LEFT_DOWN, self._on_left_down) |
||||
|
|
||||
|
sizer = wx.BoxSizer() |
||||
|
sizer.Add(self.__listbox, 1, wx.EXPAND) |
||||
|
self.SetSizer(sizer) |
||||
|
return True |
||||
|
|
||||
|
def GetAdjustedSize(self, min_width, pref_height, max_height): |
||||
|
width, height = self.GetBestSize() |
||||
|
|
||||
|
if width < min_width: |
||||
|
width = min_width |
||||
|
|
||||
|
if pref_height != -1: |
||||
|
height = pref_height * self.__listbox.GetCount() + 5 |
||||
|
|
||||
|
if height > max_height: |
||||
|
height = max_height |
||||
|
|
||||
|
return wx.Size(width, height) |
||||
|
|
||||
|
def GetControl(self): |
||||
|
return self.__listbox |
||||
|
|
||||
|
def GetStringValue(self): |
||||
|
return self.__listbox.GetString(self.value) |
||||
|
|
||||
|
#def SetStringValue(self, string): |
||||
|
#self.__listbox.SetStringSelection(string) |
||||
|
|
||||
|
|
||||
|
class CustomComboBox(wx.Panel): |
||||
|
|
||||
|
"""Custom combobox. |
||||
|
|
||||
|
Attributes: |
||||
|
CB_READONLY (long): Read-only style. The only one supported from the |
||||
|
wx.ComboBox styles. |
||||
|
|
||||
|
NAME (string): Default name for the name argument of the __init__. |
||||
|
|
||||
|
""" |
||||
|
#NOTE wx.ComboBox does not support EVT_MOTION inside the popup |
||||
|
#NOTE Tried with ComboCtrl but i was not able to draw the button |
||||
|
|
||||
|
CB_READONLY = wx.TE_READONLY |
||||
|
|
||||
|
NAME = "customComboBox" |
||||
|
|
||||
|
def __init__(self, parent, id=wx.ID_ANY, value="", pos=wx.DefaultPosition, |
||||
|
size=wx.DefaultSize, choices=[], style=0, validator=wx.DefaultValidator, name=NAME): |
||||
|
super(CustomComboBox, self).__init__(parent, id, pos, size, 0, name) |
||||
|
|
||||
|
assert style == self.CB_READONLY or style == 0 |
||||
|
|
||||
|
# Create components |
||||
|
self.textctrl = wx.TextCtrl(self, wx.ID_ANY, style=style, validator=validator) |
||||
|
tc_height = self.textctrl.GetSize()[1] |
||||
|
|
||||
|
self.button = wx.Button(self, wx.ID_ANY, "▾", size=(tc_height, tc_height)) |
||||
|
|
||||
|
# Create the ListBoxPopup in two steps |
||||
|
self.listbox = ListBoxPopup() |
||||
|
self.listbox.Init() |
||||
|
self.listbox.Create(self.listbox) |
||||
|
|
||||
|
# Set layout |
||||
|
sizer = wx.BoxSizer() |
||||
|
sizer.Add(self.textctrl, 1, wx.ALIGN_CENTER_VERTICAL) |
||||
|
sizer.Add(self.button) |
||||
|
self.SetSizer(sizer) |
||||
|
|
||||
|
# Bind events |
||||
|
self.button.Bind(wx.EVT_BUTTON, self._on_button) |
||||
|
|
||||
|
for event in ListBoxPopup.EVENTS_TABLE.values(): |
||||
|
self.listbox.Bind(wx.PyEventBinder(event.GetEventType()), self._propagate) |
||||
|
|
||||
|
# Append items since the ListBoxPopup does not have the 'choices' arg |
||||
|
self.listbox.GetControl().AppendItems(choices) |
||||
|
self.SetStringSelection(value) |
||||
|
|
||||
|
def _propagate(self, event): |
||||
|
if event.GetEventType() == wx.EVT_COMBOBOX.typeId: |
||||
|
self.textctrl.SetValue(self.listbox.GetStringValue()) |
||||
|
|
||||
|
wx.PostEvent(self, event) |
||||
|
|
||||
|
def _on_button(self, event): |
||||
|
self.Popup() |
||||
|
|
||||
|
# wx.ComboBox methods |
||||
|
|
||||
|
def Dismiss(self): |
||||
|
self.listbox.Dismiss() |
||||
|
|
||||
|
def FindString(self, string, caseSensitive=False): |
||||
|
#TODO handle caseSensitive |
||||
|
return self.listbox.GetControl().FindString(string) |
||||
|
|
||||
|
def GetCount(self): |
||||
|
return self.listbox.GetControl().GetCount() |
||||
|
|
||||
|
def GetCurrentSelection(self): |
||||
|
return self.GetSelection() |
||||
|
|
||||
|
def GetInsertionPoint(self): |
||||
|
return self.textctrl.GetInsertionPoint() |
||||
|
|
||||
|
def GetSelection(self): |
||||
|
return self.listbox.value |
||||
|
|
||||
|
def GetTextSelection(self): |
||||
|
return self.textctrl.GetSelection() |
||||
|
|
||||
|
def GetString(self, index): |
||||
|
return self.listbox.GetControl().GetString(index) |
||||
|
|
||||
|
def GetStringSelection(self): |
||||
|
return self.listbox.GetStringValue() |
||||
|
|
||||
|
def IsListEmpty(self): |
||||
|
return self.listbox.GetControl().GetCount() == 0 |
||||
|
|
||||
|
def IsTextEmpty(self): |
||||
|
return not self.textctrl.GetValue() |
||||
|
|
||||
|
def Popup(self): |
||||
|
# Calculate the position & size of the popup |
||||
|
tc_x_axis, tc_y_axis = self.textctrl.ClientToScreen((0, 0)) |
||||
|
_, tc_height = self.textctrl.GetSize() |
||||
|
_, self_y_axis = self.GetScreenPosition() |
||||
|
self_width, _ = self.GetSize() |
||||
|
_, screen_height = wx.DisplaySize() |
||||
|
|
||||
|
max_height = screen_height - (self_y_axis + tc_height) |
||||
|
|
||||
|
self.listbox.SetPosition((tc_x_axis, tc_y_axis + tc_height)) |
||||
|
self.listbox.SetSize(self.listbox.GetAdjustedSize(self_width, tc_height, max_height)) |
||||
|
|
||||
|
self.listbox.Popup() |
||||
|
|
||||
|
def SetSelection(self, index): |
||||
|
self.listbox.GetControl().SetSelection(index) |
||||
|
if self.listbox.GetControl().IsSelected(index): |
||||
|
self.listbox.value = index |
||||
|
self.textctrl.SetValue(self.listbox.GetStringValue()) |
||||
|
|
||||
|
def SetString(self, index, string): |
||||
|
self.listbox.GetControl().SetString(index, string) |
||||
|
|
||||
|
def SetTextSelection(self, from_, to_): |
||||
|
self.textctrl.SetSelection(from_, to_) |
||||
|
|
||||
|
def SetStringSelection(self, string): |
||||
|
index = self.listbox.GetControl().FindString(string) |
||||
|
self.listbox.GetControl().SetSelection(index) |
||||
|
|
||||
|
if index != wx.NOT_FOUND and self.listbox.GetControl().GetSelection() == index: |
||||
|
self.listbox.value = index |
||||
|
self.textctrl.SetValue(string) |
||||
|
|
||||
|
def SetValue(self, value): |
||||
|
self.textctrl.SetValue(value) |
||||
|
|
||||
|
# wx.ItemContainer methods |
||||
|
|
||||
|
def Clear(self): |
||||
|
self.textctrl.Clear() |
||||
|
self.listbox.GetControl().Clear() |
||||
|
|
||||
|
def Append(self, item): |
||||
|
self.listbox.GetControl().Append(item) |
||||
|
|
||||
|
def AppendItems(self, items): |
||||
|
self.listbox.GetControl().AppendItems(items) |
||||
|
|
||||
|
def Delete(self, index): |
||||
|
self.listbox.GetControl().Delete(index) |
||||
|
|
||||
|
# wx.TextEntry methods |
||||
|
|
||||
|
def GetValue(self): |
||||
|
return self.textctrl.GetValue() |
||||
|
|
||||
|
# ListBoxWithHeaders methods |
||||
|
|
||||
|
def add_header(self, header): |
||||
|
self.listbox.GetControl().add_header(header) |
||||
|
|
||||
|
def add_item(self, item, with_prefix=True): |
||||
|
self.listbox.GetControl().add_item(item, with_prefix) |
||||
|
|
||||
|
def add_items(self, items, with_prefix=True): |
||||
|
self.listbox.GetControl().add_items(items, with_prefix) |
Write
Preview
Loading…
Cancel
Save