1. EzWpfPython
import clr
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore");
clr.AddReference('WindowsBase')
clr.AddReference('System.Data')
clr.AddReference('System.ComponentModel')
clr.AddReference('System.Windows.Forms')
import System
from System import *
from System.Data import *
from System.Type import GetType
from System.Threading.Tasks import Task
from System.ComponentModel import SortDescription
from System.ComponentModel import ListSortDirection
from System.Windows import *
from System.Windows.Controls import *
from System.Windows.Controls.Primitives import *
from System.Windows.Media import *
from System.Windows.Media.Imaging import *
from System.Windows.Media.Effects import *
from System.Windows.Shapes import Rectangle
from System.Windows.Data import Binding
from System.Windows.Data import CollectionViewSource
from System.Windows.Ink import Stroke
from System.Windows.Forms import ( FolderBrowserDialog, DialogResult )
from Microsoft.Win32 import ( OpenFileDialog, SaveFileDialog )
'''
System::
Data, Uri, UriKind, Timers, Threading, IO
System.Windows::
Application, Window, Clipboard, DataFormats, Visibility, Thickness,
TextWrapping, HorizontalAlignment, VerticalAlignment, MessageBox,
MessageBoxButton, MessageBoxResult, GridUnitType, GridLength,
TextAlignment
System.Windows.Controls::
GroupBox, Border, StackPanel, Orientation,
Grid. RowDefinition. ColumnDefinition, TabControl, TabItem,
ContextMenu, Menu, MenuItem, ToolTip, Separator, Image
Label, TextBlock, Button, CheckBox, TextBox, ComboBox, ListBox
ListView, ListViewItem, TreeView, TreeViewItem, GridView
GridViewColumn, ProgressBar, DatePicker, Slider, ScrollViewer
WebBrowser, ToolBarTray, ToolBar, ScrollBarVisibility, Canvas
System.Windows.Controls.Primitives
ToggleButton, TickPlacement, StatusBar, StatusBarItem
System.Windows.Media
Brushes, Stretch, VisualTreeHelper
System.Windows.Media.Imaging
BitmapImage, BitmapFrame
System.Data
DataTable DataView DataColumn
System.Windows.Forms
FolderBrowserDialog DialogResult
'''
#
# Control Table
#
_window__ctrl_table = {}
def GetControl(name):
return _window__ctrl_table.get(name)
def GetWpfControl(name):
if _window__ctrl_table.get(name): return _window__ctrl_table[name].ctrl;
def DumpControlTable():
for k,v in _window__ctrl_table.items():
print(k,v)
#
# Controls
#
class Class:
def __init__(self,**kwargs): self.__dict__.update(kwargs)
def GetHandler(handler):
return lambda sender,args: handler(Class(sender=sender,args=args))
'''
def Handler(sender,args):
handler(Class(sender=sender,args=args))
return Handler
'''
class WpfControl():
def Initialize(self,h):
if h.get('key'): _window__ctrl_table[h['key']] = self
if h.get('tooltip'): self.SetToolTip(h['tooltip'])
if h.get('menu'): self.SetContextMenu(h['menu'])
if h.get('width'): self.ctrl.Width = h['width']
if h.get('height'): self.ctrl.Height = h['height']
if h.get('drop'): self.SetFileDropHandler(h['drop'])
self.ctrl.Margin = Thickness(5)
self.ctrl.Padding = Thickness(1)
def SetMargin(self,l,t,r,b):
self.ctrl.Margin = System.Windows.Thickness(l,t,r,b)
def ShadowEffect(self):
from System.Windows.Media.Effects import DropShadowBitmapEffect
self.ctrl.BitmapEffect = DropShadowBitmapEffect()
def SetFontSize(self,size):
self.ctrl.FontSize = size
def SetToolTip(self,tooltip):
tip = ToolTip()
tip.Content = tooltip
self.ctrl.ToolTip = tip
def SetContextMenu(self,menu_table):
menu = ContextMenu()
for m in menu_table:
menu.Items.Add(WpfMenu(m['name'],m['item']).ctrl)
self.ctrl.ContextMenu = menu
def SetFileDropHandler(self,handler):
SetFileDropHandler(self.ctrl,handler)
class WpfSpacer(WpfControl):
def __init__(self,h):
self.ctrl = Label()
if not h.get('width'): h['expand'] = True
self.Initialize(h)
def SetValue(self,text):
self.ctrl.Content = text
class WpfLabel(WpfControl):
def __init__(self,h):
self.ctrl = Label()
self.Initialize(h)
if h.get('label'): self.SetValue(h['label'])
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
def SetValue(self,text):
self.ctrl.Content = text
class WpfImageView(WpfControl):
def __init__(self,h):
self.ctrl = Label()
self.Initialize(h)
self.image = Image()
self.image.HorizontalAlignment = HorizontalAlignment.Center
self.image.VerticalAlignment = VerticalAlignment.Center
if h.get('image'): self.image.Source = BitmapImage(System.Uri(h['image'],System.UriKind.Relative))
if h.get('stretch'): self.Stretch(h['stretch'])
else: self.StretchUniform()
if h.get('size'): self.image.Height = float(h['size']); self.image.Width = float(h['size'])
if h.get('scroll') and h['scroll']:
scroll = ScrollViewer()
scroll.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
scroll.Content = self.image;
self.ctrl.Content = scroll
elif h.get('multiple') and h['multiple']:
stack = StackPanel()
stack.Orientation = Orientation.Horizontal
stack.Children.Add(self.image)
self.ctrl.Content = stack
else:
self.ctrl.Content = self.image
def StretchNone(self): self.image.Stretch = Stretch.None
def StretchFill(self): self.image.Stretch = Stretch.Fill
def StretchUniform(self): self.image.Stretch = Stretch.Uniform
def StretchUniformToFill(self): self.image.Stretch = Stretch.UniformToFill
def Stretch(self,stretch):
if stretch == 'none': self.StretchNone()
elif stretch == 'fill': self.StretchFill()
elif stretch == 'uniform': self.StretchUniform()
elif stretch == 'uniformfill': self.StretchUniformToFill()
class WpfButton(WpfControl):
def __init__(self,h):
self.ctrl = Button()
self.Initialize(h)
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
if h.get('handler'): self.ctrl.Click += GetHandler(h['handler'])
stack = StackPanel()
if h.get('orientation') and h['orientation'] == 'vertical':
stack.Orientation = Orientation.Vertical
else:
stack.Orientation = Orientation.Horizontal
self.ctrl.Content = stack
if h.get('image'):
image = Image()
image.Source = BitmapImage(System.Uri(h['image'],System.UriKind.Relative))
image.VerticalAlignment = VerticalAlignment.Center
image.Stretch = Stretch.Fill #Stretch.None
if h.get('size'): image.Height = float(h['size']); image.Width = float(h['size'])
stack.Children.Add(image)
if h.get('label'):
text = TextBlock()
text.Text = h['label']
text.TextAlignment = TextAlignment.Center
stack.Children.Add(text);
class WpfToggleButton(WpfControl):
def __init__(self,h):
self.ctrl = ToggleButton()
self.Initialize(h)
if h.get('label'): self.ctrl.Content = h.get('label')
if h.get('handler'): self.ctrl.Click += GetHandler(h['handler'] )
def IsSelected(self):
return self.ctrl.IsChecked
class WpfCheckBox(WpfControl):
def __init__(self,h):
self.ctrl = CheckBox()
self.ctrl.VerticalAlignment = VerticalAlignment.Center
self.ctrl.VerticalContentAlignment = VerticalAlignment.Center
self.Initialize(h)
if h.get('label'): self.ctrl.Content = h['label']
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
if h.get('handler'): self.ctrl.Click += GetHandler(h['handler'] )
def GetValue(self): return self.ctrl.IsChecked
class WpfTextBox(WpfControl):
def __init__(self,h):
self.text = TextBox()
self.ctrl = self.text
self.Initialize(h)
if h.get('width'): self.SetWidth(h['width'])
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
if h.get('multiline'):
self.ctrl.AcceptsReturn = True
self.ctrl.AcceptsTab = True
self.ctrl.TextWrapping = TextWrapping.NoWrap
self.ctrl.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto
self.ctrl.VerticalScrollBarVisibility = ScrollBarVisibility.Auto
if h.get('toolbar') and h['toolbar']:
self.vbox = WpfVBox()
self.hbox = WpfHBox()
self.hbox.AddItem(self.Button("Clear", self.ClearHandler))
self.hbox.AddItem(self.Button("Copy", self.CopyHandler))
self.hbox.AddItem(self.Button("CopyAll", self.CopyAllHandler))
self.hbox.AddItem(self.Button("Paste", self.PasteHandler))
self.hbox.AddItem(self.Button("PasteHtml", self.PasteHtmlHandler))
self.vbox.AddItem(self.hbox.ctrl)
self.vbox.AddItem(self.text,{'expand':True})
self.ctrl = self.vbox.ctrl
def Button(self,label,handler):
button = Button()
button.Content = label
button.Click += handler
return button
def ClearHandler(self,sender,args):
self.text.Clear()
def CopyHandler(self,sender,args):
self.text.Copy()
def CopyAllHandler(self,sender,args):
self.text.SelectAll()
self.text.Copy()
def PasteHandler(self,sender,args):
self.text.Paste()
def PasteHtmlHandler(self,sender,args):
self.text.Text = ClipboardGetHtmlData()
def Clear(self):
self.text.Text = ""
def GetValue(self):
return self.text.Text
def SetValue(self,text):
self.text.Text = text
def AppendText(self,text):
self.text.Text += text
def SetWidth(self,width):
self.text.Width = width
def ScrollToEnd(self):
self.text.ScrollToEnd()
def SetWrap(self,wrap):
self.text.TextWrapping = TextWrapping.Wrap if wrap else TextWrapping.NoWrap
class WpfChoiceBox(WpfControl):
def __init__(self,h):
self.ctrl = ComboBox()
self.Initialize(h)
self.init_ComboBox(h)
def init_ComboBox(self,h):
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
if h.get('handler'): self.ctrl.SelectionChanged += GetHandler(h['handler'] )
if h.get('items'):
self.ctrl.ItemsSource = h['items']
self.ctrl.SelectedIndex = 0
def GetValue(self): return ctrl.Text
def GetAddedItem(self,args): return args.AddedItems[0]
class WpfComboBox(WpfChoiceBox):
def __init__(self,h):
self.ctrl = ComboBox()
self.Initialize(h)
self.init_ComboBox(h)
self.ctrl.IsEditable=True
self.ctrl.IsReadOnly=False
class WpfListBox(WpfControl):
def __init__(self,h):
self.ctrl = ListBox()
self.Initialize(h)
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
if h.get('handler'): self.ctrl.SelectionChanged += GetHandler(h['handler'] )
if h.get('items'):
self.ctrl.ItemsSource = h['items']
self.ctrl.SelectedIndex = 0
def GetValue(self): return self.ctrl.SelectedItem
class WpfTableView(WpfControl):
def __init__(self,h):
self.ctrl = ListView()
self.table = DataTable('table')
self.Initialize(h)
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
#if h.get('handler'): self.ctrl.SelectionChanged += h['handler']
if h.get('handler'): self.ctrl.SelectionChanged += GetHandler(h['handler'])
self.grid = GridView()
self.grid.AllowsColumnReorder = True;
self.grid.ColumnHeaderToolTip = "ListView Column Info";
if h.get('columns'):
items = h['columns']
widths = None
labels = None
if h.get('widths'): widths = h['widths']
if h.get('labels'): labels = h['labels']
for i in range(0,len(items)):
width = widths[i] if widths else None
label = labels[i] if labels else None
self.AddColumn(items[i],width,label)
self.ctrl.View = self.grid
self.ctrl.ItemsSource = self.table.DefaultView
self.ctrl.AddHandler(GridViewColumnHeader.ClickEvent, RoutedEventHandler(self.OnColumnHeaderClick))
self.sort_dir = ListSortDirection.Ascending
def AddColumn(self,name,width=None,label=None):
col = GridViewColumn()
if width: col.Width = width
col.Header = label if label else name
col.DisplayMemberBinding = Binding(name)
self.grid.Columns.Add(col);
item = DataColumn(name, GetType("System.String"))
self.table.Columns.Add(item)
'''
item = DataColumn()
item.DataType = System.Type.GetType("System.String");
item.ColumnName = name
item.AutoIncrement = False
item.Header = label #if label else name
item.ReadOnly = False
item.Unique = False
self.table.Columns.Add(item)
'''
def AddItem(self,items):
item = self.table.NewRow()
for key, value in items.items():
item[key] = value;
self.table.Rows.Add(item);
def GetValue(self): return self.ctrl.SelectedItem
def GetSelectedItems(self): return self.ctrl.SelectedItems
def AddSortColumnName(self,col_name,ascending=True):
view = CollectionViewSource.GetDefaultView(self.ctrl.ItemsSource)
if ascending:
view.SortDescriptions.Add(SortDescription(col_name, ListSortDirection.Ascending))
else:
view.SortDescriptions.Add(SortDescription(col_name, ListSortDirection.Descending))
def ColumnSort(self,col_name,direction):
view = CollectionViewSource.GetDefaultView(self.ctrl.ItemsSource)
view.SortDescriptions.Clear()
view.SortDescriptions.Add(SortDescription(col_name, direction))
view.Refresh()
def OnColumnHeaderClick(self,sedner,event):
headerClicked = event.OriginalSource
columnBinding = headerClicked.Column.DisplayMemberBinding
if self.sort_dir == ListSortDirection.Descending:
self.sort_dir = ListSortDirection.Ascending
headerClicked.Column.Header = columnBinding.Path.Path + " (+)"
else:
self.sort_dir = ListSortDirection.Descending
headerClicked.Column.Header = columnBinding.Path.Path + " (-)"
self.ColumnSort( columnBinding.Path.Path, self.sort_dir ) #headerClicked.Column.Header
class WpfTreeView(WpfControl):
def __init__(self,h):
self.root = TreeViewItem()
self.root.Header = h['name']
self.root.IsExpanded = True
self.ctrl = TreeView()
self.ctrl.Items.Add(self.root)
self.Initialize(h)
if h.get('handler'): self.ctrl.SelectedItemChanged += GetHandler(h['handler'] )
def AddRootItem(self,label):
return self.AddItem(label)
def AddItem(self,label,parent=None):
item = TreeViewItem()
item.Header = label
item.IsExpanded = True
if parent: parent.Items.Add(item)
else: self.root.Items.Add(item)
return item
def GetSelectedIndex(self):
pass
def GetSelectedItem(self):
return self.ctrl.SelectedItem
def GetSelectedItemText(self):
return self.ctrl.SelectedItem.Header.ToString()
def GetSelectedItemPath(self,delim=""):
item = self.ctrl.SelectedItem
return self.GetItemPath(item,delim)
def GetItemPath(self,item,delim=""):
path = item.Header.ToString()
while type(item.Parent) == TreeViewItem:
item = item.Parent
path = item.Header.ToString() + delim + path
return path
def GetParentItem(self,item):
return item.Parent
def GetItemValue(self,item):
return item.ToString()
class WpfWebView(WpfControl):
def __init__(self,h):
self.web = WebBrowser()
self.ctrl = self.web
self.web.Navigated += self.LoadedHandler
if h.get('fontsize'): self.SetFontSize(h['fontsize'])
if h.get('toolbar') and h['toolbar']:
self.vbox = WpfVBox()
self.hbox = WpfHBox()
self.text = TextBox()
self.hbox.AddItem(self.Button("<-", self.BackHandler))
self.hbox.AddItem(self.Button("->", self.ForwardHandler))
self.hbox.AddItem(self.Button("<>", self.RefreshHandler))
self.hbox.AddItem(self.text, {'expand':True})
self.hbox.AddItem(self.Button("Go", self.GoHandler))
self.vbox.AddItem(self.hbox.ctrl)
self.vbox.AddItem(self.web,{'expand':True})
self.ctrl = self.vbox.ctrl
if h.get('uri'): self.Go(h['uri'])
def Button(self,label,handler):
button = Button()
button.Content = label
button.Click += handler
return button
def LoadedHandler(self,sender,args):
self.text.Text = self.web.Source.ToString()
def GoHandler(self,sender,args):
uri = self.text.Text
if not uri.startswith('http'):
uri = "http://" + uri
self.text.Text = uri
self.Go(uri)
def BackHandler(self,sender,args): self.Back()
def ForwardHandler(self,sender,args): self.Forward()
def RefreshHandler(self,sender,args): self.Refresh()
def Go(self,uri): self.web.Navigate(System.Uri(uri, System.UriKind.RelativeOrAbsolute));
def Back(self):
if self.web.CanGoBack: self.web.GoBack()
def Forward(self):
if self.web.CanGoForward: self.web.GoForward()
def Refresh(self):
self.web.Refresh()
def Html(self): return self.web.Document.documentElement.InnerHtml
class WpfProgressBar(WpfControl):
def __init__(self,h):
self.ctrl = ProgressBar()
#self.ctrl.IsIndeterminate = True
#self.ctrl.Margin = new Thickness(10,0,10,10);
self.ctrl.Visibility = Visibility.Visible;
self.ctrl.Width = 100;
self.ctrl.Height = 16;
#self.ctrl.Foreground = System.Windows.Media.Brushes.Green;
#self.ctrl.Background = System.Windows.Media.Brushes.Red;
#self.ctrl.Style = ProgressBarStyle.Continuous #Marquee
self.ctrl.Maximum = 100
self.ctrl.Value = 0
#self.ctrl.FlowDirection = FlowDirection.LeftToRight
self.Initialize(h)
def GetValue(self):
return self.ctrl.Value
def SetValue(self,v):
self.ctrl.Value = v
class WpfDatePicker(WpfControl):
def __init__(self,h):
self.ctrl = DatePicker()
self.Initialize(h)
if h.get('handler'): self.ctrl.SelectedDateChanged += GetHandler(h['handler'] )
def GetValue(self):
return self.ctrl.Text
def SetValue(self,v):
self.ctrl.Text = v
class WpfSlider(WpfControl):
def __init__(self,h):
self.ctrl = Slider()
self.Initialize(h)
if h.get('handler'): self.ctrl.ValueChanged += GetHandler(h['handler'] )
self.ctrl.Width = 100;
self.ctrl.Height = 16;
self.ctrl.Minimum = h['min'] if h.get('min') else 0
self.ctrl.Maximum = h['max'] if h.get('max') else 100
self.ctrl.Value = h['value'] if h.get('value') else 0
self.ctrl.SmallChange = 1
self.ctrl.LargeChange = 10
self.ctrl.TickPlacement = TickPlacement.BottomRight
self.ctrl.TickFrequency = 10
def GetValue(self):
return self.ctrl.Value
def SetValue(self,v):
self.ctrl.Value = v
#
# Containers
#
class WpfBorderGrid():
def __init__(self):
self.grid = Grid()
self.ctrl = Border()
self.ctrl.HorizontalAlignment = HorizontalAlignment.Left
self.ctrl.VerticalAlignment = VerticalAlignment.Top
#border.BorderBrush = BorderBrush.Black
self.ctrl.BorderThickness = 2
self.ctrl.Content = self.grid
def AddRow(self,height=1,expand=False,span=1):
if expand: length = GridLength(height, GridUnitType.Star)
else: length = GridLength(height, GridUnitType.Auto)
self.grid.RowDefinitions.Add(RowDefinition(Height = length))
def AddColumn(self,width=1,expand=False,span=1):
if expand: length = GridLength(width, GridUnitType.Star)
else: length = GridLength(width, GridUnitType.Auto)
self.grid.ColumnDefinitions.Add(ColumnDefinition(Width = length))
def AddItem(self,item,row,col,rowspan=1,colspan=1):
Grid.SetRow(item, row);
Grid.SetColumn(item, col);
self.grid.Children.Add(item)
if rowspan > 1: item.SetValue(Grid.RowSpanProperty, rowspan);
if colspan > 1: item.SetValue(Grid.ColumnSpanProperty, colspan);
class WpfGrid():
def __init__(self):
self.ctrl = Grid()
def AddRow(self,height=1,expand=False,span=1):
if expand: length = GridLength(height, GridUnitType.Star)
else: length = GridLength(height, GridUnitType.Auto)
self.ctrl.RowDefinitions.Add(RowDefinition(Height = length))
def AddColumn(self,width=1,expand=False,span=1):
if expand: length = GridLength(width, GridUnitType.Star)
else: length = GridLength(width, GridUnitType.Auto)
self.ctrl.ColumnDefinitions.Add(ColumnDefinition(Width = length))
def AddItem(self,item,row,col,rowspan=1,colspan=1):
Grid.SetRow(item, row);
Grid.SetColumn(item, col);
self.ctrl.Children.Add(item)
if rowspan > 1: item.SetValue(Grid.RowSpanProperty, rowspan);
if colspan > 1: item.SetValue(Grid.ColumnSpanProperty, colspan);
class WpfVBox():
def __init__(self):
self.ctrl = Grid()
self.ctrl.Margin = Thickness(1)
self.rows = 0
def AddItem(self,item,attr=None,height=1):
if attr and attr.get('expand'): length = GridLength(height, GridUnitType.Star)
else: length = GridLength(height, GridUnitType.Auto)
self.ctrl.RowDefinitions.Add(RowDefinition(Height = length))
Grid.SetRow(item, self.rows);
if attr and attr.get('group'):
group = GroupBox()
group.Header = attr['group']
group.AddChild(item)
Grid.SetRow(group, self.rows);
self.ctrl.Children.Add(group)
else:
if attr and attr.get('border') and attr['border']:
rect = Rectangle()
rect.Stroke = Brushes.Gray
rect.Fill = Brushes.Transparent
Grid.SetRow(rect, self.rows);
self.ctrl.Children.Add(rect)
self.ctrl.Children.Add(item)
self.rows = self.rows + 1
def AddSplitter(self,width=1):
from System.Windows.Controls import GridSplitter
item = GridSplitter()
item.HorizontalAlignment = HorizontalAlignment.Stretch
item.VerticalAlignment = VerticalAlignment.Center
item.ShowsPreview = True
item.Height = 5
length = GridLength(width, GridUnitType.Auto)
self.ctrl.RowDefinitions.Add(RowDefinition(Height = length))
Grid.SetRow(item, self.rows);
self.ctrl.Children.Add(item)
self.rows = self.rows + 1
class WpfHBox():
def __init__(self):
self.ctrl = Grid()
self.ctrl.Margin = Thickness(1)
self.cols = 0
def AddItem(self,item,attr=None,width=1):
if attr and attr.get('expand'): length = GridLength(width, GridUnitType.Star)
else: length = GridLength(width, GridUnitType.Auto)
self.ctrl.ColumnDefinitions.Add(ColumnDefinition(Width = length))
Grid.SetColumn(item, self.cols);
if attr and attr.get('group'):
group = GroupBox()
group.Header = attr['group']
group.AddChild(item)
Grid.SetColumn(group, self.cols);
self.ctrl.Children.Add(group)
else:
if attr and attr.get('border') and attr['border']:
rect = Rectangle()
rect.Stroke = Brushes.Gray
rect.Fill = Brushes.Transparent
Grid.SetColumn(rect, self.cols);
self.ctrl.Children.Add(rect)
self.ctrl.Children.Add(item)
self.cols = self.cols + 1
def AddSplitter(self,width=1):
from System.Windows.Controls import GridSplitter
item = GridSplitter()
item.HorizontalAlignment = HorizontalAlignment.Center
item.VerticalAlignment = VerticalAlignment.Stretch
item.ShowsPreview = True
item.Width = 5
length = GridLength(width, GridUnitType.Auto)
self.ctrl.ColumnDefinitions.Add(ColumnDefinition(Width = length))
Grid.SetColumn(item, self.cols);
self.ctrl.Children.Add(item)
self.cols = self.cols + 1
class WpfBorder():
def __init__(self):
self.ctrl = Border()
self.ctrl.HorizontalAlignment = HorizontalAlignment.Left
self.ctrl.VerticalAlignment = VerticalAlignment.Top
self.ctrl.Background = Brushes.SkyBlue
self.ctrl.BorderBrush = Brushes.Black
self.ctrl.BorderThickness = Thickness(1)
def SetChild(self,ctrl):
self.ctrl.Child = ctrl
class WpfStackBox():
def __init__(self):
self.ctrl = StackPanel()
self.ctrl.Margin = Thickness(1)
def Add(self,item):
self.ctrl.Children.Add(item)
class WpfGroupBox():
def __init__(self,h):
self.ctrl = GroupBox()
if h.get('label'): self.ctrl.Header = h['label']
if h.get('item'):
self.AddItem(WpfLayout(h['item']))
def AddItem(self,item):
self.ctrl.AddChild(item)
class WpfTabPane():
def __init__(self,h):
self.ctrl = TabControl()
self.ctrl.Margin = System.Windows.Thickness(15)
labels = h.get('labels')
items = h.get('items')
if labels and items:
for i in range(0,len(items)):
self.AddItem( labels[i], WpfLayout(items[i]))
def AddItem(self,label,layout):
tab = TabItem()
tab.Header = label
tab.Content = layout
self.ctrl.Items.Add(tab)
class WpfHSplitPane():
def __init__(self,h):
self.box = WpfHBox()
self.ctrl = self.box.ctrl
self.ctrl.Margin = Thickness(1)
items = h.get('items')
width = [ 1, 1 ]
if h.get('first'):
width[0] = float(h['first']) * 10
width[1] = 10 - width[0]
self.box.AddItem(WpfLayout(items[0]),{'expand':True},width[0])
self.box.AddSplitter()
self.box.AddItem(WpfLayout(items[1]),{'expand':True},width[1])
class WpfVSplitPane():
def __init__(self,h):
self.box = WpfVBox()
self.ctrl = self.box.ctrl
self.ctrl.Margin = System.Windows.Thickness(1)
items = h.get('items')
height = [ 1, 1 ]
if h.get('first'):
height[0] = float(h['first']) * 10
height[1] = 10 - height[0]
self.box.AddItem(WpfLayout(items[0]),{'expand':True},height[0])
self.box.AddSplitter()
self.box.AddItem(WpfLayout(items[1]),{'expand':True},height[1])
class WpfMenu():
def __init__(self,name,menu_table):
self.ctrl = MenuItem()
self.ctrl.Header = name;
for m in menu_table:
if not m.get('name') or m['name'] == '-':
self.ctrl.Items.Add(Separator())
continue
if not m.get('item'): continue # Disabled
if type(m['item']) == list:
self.ctrl.Items.Add(WpfMenu(m['name'],m['item']).ctrl)
else:
item = MenuItem()
if m.get('name'): item.Header = m['name']
if m.get('image'):
image = Image()
image.Source = BitmapImage(System.Uri(m['image'],System.UriKind.Relative))
item.Icon = image
if m.get('item'): item.Click += m['item']
if m.get('tooltip'):
tooltip = ToolTip()
tooltip.Content = m['tooltip']
item.ToolTip = tooltip
self.ctrl.Items.Add(item)
def WpfMenuBar(menu_table):
ctrl = Menu()
ctrl.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
ctrl.VerticalAlignment = System.Windows.VerticalAlignment.Top;
for m in menu_table:
ctrl.Items.Add(WpfMenu(m['name'],m['item']).ctrl)
return ctrl
def WpfToolBar(tool_table):
tray = ToolBarTray()
for v in tool_table:
ctrl = ToolBar()
ctrl.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
ctrl.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
for h in v:
name = h['name']
f = None
if name == 'Label': f = WpfLabel(h)
elif name == 'Button': f = WpfButton(h)
elif name == 'ToggleButton': f = WpfToggleButton(h)
elif name == 'CheckBox': f = WpfCheckBox(h)
elif name == 'TextField': f = WpfTextBox(h)
elif name == 'ChoiceBox': f = WpfChoiceBox(h)
elif name == 'ComboBox': f = WpfComboBox(h)
elif name == 'ProgressBar': f = WpfProgressBar(h)
elif name == 'DatePicker': f = WpfDatePicker(h)
elif name == 'Slider': f = WpfSlider(h)
if f: ctrl.Items.Add(f.ctrl)
tray.AddChild(ctrl)
return tray
def WpfStatusBar(status_table):
ctrl = StatusBar()
ctrl.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
ctrl.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
for h in status_table:
if h.get('name'):
name = h['name']
if name == 'Label': f = WpfLabel(h)
elif name == 'Button': f = WpfButton(h)
elif name == 'ToggleButton': f = WpfToggleButton(h)
elif name == 'CheckBox': f = WpfCheckBox(h)
elif name == 'TextField': f = WpfTextBox(h)
elif name == 'ChoiceBox': f = WpfChoiceBox(h)
elif name == 'ComboBox': f = WpfComboBox(h)
elif name == 'ProgressBar': f = WpfProgressBar(h)
elif name == 'DatePicker': f = WpfDatePicker(h)
elif name == 'Slider': f = WpfSlider(h)
item = StatusBarItem()
item.Content = f.ctrl
ctrl.Items.Add(item)
return ctrl
def WpfLayout(content):
vbox = WpfVBox()
for v in content:
hbox = WpfHBox()
attr = None
for h in v:
name = h.get('name')
if not name:
attr = h
else:
if name == 'Spacer': f = WpfSpacer(h)
elif name == 'Label': f = WpfLabel(h)
elif name == 'ImageView': f = WpfImageView(h)
elif name == 'Button': f = WpfButton(h)
elif name == 'ToggleButton': f = WpfToggleButton(h)
elif name == 'CheckBox': f = WpfCheckBox(h)
elif name == 'TextField': f = WpfTextBox(h)
elif name == 'ChoiceBox': f = WpfChoiceBox(h)
elif name == 'ComboBox': f = WpfComboBox(h)
elif name == 'ProgressBar': f = WpfProgressBar(h)
elif name == 'DatePicker': f = WpfDatePicker(h)
elif name == 'Slider': f = WpfSlider(h)
elif name == 'TextArea': h['multiline'] = True; f = WpfTextBox(h)
elif name == 'ListBox': f = WpfListBox(h)
elif name == 'TreeView': f = WpfTreeView(h)
elif name == 'TableView': f = WpfTableView(h)
elif name == 'WebView': f = WpfWebView(h)
elif name == 'GroupBox': f = WpfGroupBox(h)
elif name == 'TabPane': f = WpfTabPane(h)
elif name == 'HSplit': f = WpfHSplitPane(h)
elif name == 'VSplit': f = WpfVSplitPane(h)
else: continue
hbox.AddItem(f.ctrl,h)
'''
elif name == 'ScrollImageView': f = WpfScrollImageView(h,parent)
elif name == 'ProgressBar': f = WpfProgressBar(h)
'''
vbox.AddItem(hbox.ctrl,attr)
return vbox.ctrl
#
# API
#
#
# Thread, Execute
#
'''
def RunLater(handler):
from System import Action
System.Windows.Threading.DispatcherExtensions.BeginInvoke(
System.Windows.Threading.Dispatcher.CurrentDispatcher, Action(handler))
'''
def RunLater(ctrl,handler):
ctrl.Dispatcher.BeginInvoke(System.Action(handler))
def Execute(cmd):
import subprocess
try:
out = subprocess.check_output(cmd)
return 0,out
except:
return -1,""
def StartTimer(handler,msec):
aTimer = System.Timers.Timer(msec)
aTimer.Elapsed += GetHandler(handler)
aTimer.AutoReset = True
#aTimer.Enabled = True
aTimer.Start()
#aTimer.Stop();
#aTimer.Dispose();
def StartThread(handler):
import threading
thread = threading.Thread(target=handler)
thread.daemon = True
thread.start()
def StartTask(handler):
Task.Factory.StartNew(handler)
#
# File Drop
#
def DragEnter(sender, event):
if event.Data.GetDataPresent(DataFormats.FileDrop):
event.Effect = DragDropEffects.All
else:
event.Effect = DragDropEffects.None
def DragOver(sender, event):
if event.Data.GetDataPresent(DataFormats.FileDrop):
event.Effect = DragDropEffects.Copy
def DragDropped(handler):
def DropHandler(sender, event):
if event.Data.GetDataPresent(DataFormats.FileDrop):
files = event.Data.GetData(DataFormats.FileDrop)
handler(files)
return DropHandler
def SetFileDropHandler(ctrl,handler):
ctrl.AllowDrop = True
#ctrl.DragEnter += DragEnter
#ctrl.DragOver += DragOver
ctrl.Drop += DragDropped(handler)
#
# Clipboard
#
def ClipboardGetTextData():
return Clipboard.GetData(DataFormats.Text)
def ClipboardSetTextData(text):
Clipboard.SetData(DataFormats.Text, text)
def ClipboardGetHtmlData():
return Clipboard.GetData(DataFormats.Html)
def ClipboardSetHtmlData(text):
Clipboard.SetData(DataFormats.Html, text)
def ClipboardGetText():
return Clipboard.GetText()
def ClipboardSetText(text):
Clipboard.SetText(text)
#
# Dialog
#
def WpfAlertDialog(message,title=None):
if title: MessageBox.Show(message,title)
else: MessageBox.Show(message)
def WpfYesNoDialog(message,title,icon=System.Windows.MessageBoxImage.Information):
rv = MessageBox.Show(message,title,MessageBoxButton.YesNo,icon)
if rv == MessageBoxResult.Yes: return True
else: return False
def WpfYesNoCancelDialog(message,title,icon=System.Windows.MessageBoxImage.Information):
rv = MessageBox.Show(message,title,MessageBoxButton.YesNoCancel,icon)
if rv == MessageBoxResult.Yes: return True
elif rv == MessageBoxResult.No: return False
else: return None
def WpfFileOpenDialog(initialFile=None,multiselect=False):
dlg = OpenFileDialog()
dlg.Multiselect = multiselect
dlg.DefaultExt = ".txt"; # Default file extension
dlg.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
if initialFile:
dlg.InitialDirectory = System.IO.Path.GetDirectoryName(initialFile)
dlg.FileName = System.IO.Path.GetFileName(initialFile)
#Directory.GetParent(initialFile) #Path.GetFileName(initialFile)
if dlg.ShowDialog() == True:
return dlg.FileNames
def WpfFileSaveDialog(initialFile=None):
dlg = SaveFileDialog()
dlg.DefaultExt = ".txt"; # Default file extension
dlg.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
if initialFile:
dlg.InitialDirectory = System.IO.Path.GetDirectoryName(initialFile)
dlg.FileName = System.IO.Path.GetFileName(initialFile)
if dlg.ShowDialog() == True:
return dlg.FileNames
def WpfDirectoryOpenDialog(initialDirectory=None):
dlg = FolderBrowserDialog()
dlg.ShowNewFolderButton = True
if initialDirectory:
dlg.SelectedPath = initialDirectory #Path.GetFileName(initialFile)
if dlg.ShowDialog() != DialogResult.Cancel:
return dlg.SelectedPath
#
# Window
#
class WpfWindow(Window):
def __init__(self,title="",width=800,height=600):
print('WpfWindow.__init__()')
self.ctrl = None
self.stage = None
self.createdHandler = None
self.closeHandler = None
self.title = None
self.icon = None
self.width = 800
self.height = 600
self.menu = None
self.tool = None
self.status = None
self.content = None
def Popup(self):
self.box = WpfVBox()
if self.menu: self.box.AddItem(WpfMenuBar(self.menu),{'expand':False})
if self.tool: self.box.AddItem(WpfToolBar(self.tool),{'expand':False})
if self.content: self.box.AddItem(WpfLayout(self.content),{'expand':True})
if self.status: self.box.AddItem(WpfStatusBar(self.status),{'expand':False})
self.Content = self.box.ctrl
if self.createdHandler: self.createdHandler()
self.Show()
def Run(self):
self.Popup()
Application().Run(self)
def SetTitle(self,title): self.Title = title
def SetSize(self,width,height): self.Width = width; self.Height = height
def SetIcon(self,icon): self.Icon = BitmapFrame.Create(System.Uri(icon, System.UriKind.RelativeOrAbsolute))
def SetMenuBar(self,menu): self.menu = menu
def SetToolBar(self,tool): self.tool = tool
def SetStatusBar(self,status): self.status = status
def SetContent(self,content): self.content = content
def SetCreatedHandler(self,handler): self.createdHandler = handler
def SetCloseHandler(self,handler): self.Closing += GetHandler(handler)
def SetFileDropHandler(self,handler): SetFileDropHandler(self,handler)
#
# Application
#
def onExit(event):
System.Windows.Application.Current.Shutdown();
def onAbout(event):
WpfAlertDialog("Hello, world!", "My App");
def printText(text):
ctrl = GetControl('textarea')
if ctrl:
ctrl.AppendText(text + '\n')
ctrl.ScrollToEnd()
def onChoice(event):
ctrl = GetControl('choice')
if ctrl: printText("Selected: " + ctrl.GetAddedItem(event.args) + "\n")
def onCheck(event):
ctrl = GetControl('check')
if ctrl: printText("Checked: " + ctrl.GetValue().ToString() + "\n")
def onListBox(event):
ctrl = GetControl('listbox')
if ctrl: printText("List Selected: " + ctrl.GetValue().ToString() + "\n")
def onListView(event): #event
ctrl = GetControl('listbox')
listview = GetControl('table')
#row = listview.GetValue()
#printText(row['col1'] + "," + row['col2'])
rows = listview.GetSelectedItems()
for row in rows:
printText(row['Name'] + "," + row['Age'])
def onBrowse(event):
ctrl = GetControl('textfile')
files = WpfFileOpenDialog()
if files: ctrl.SetValue(files[0])
def onBrowseFolder(event):
ctrl = GetControl('textfile')
folder = WpfDirectoryOpenDialog()
if folder: ctrl.SetValue(folder)
def onToggle(event):
ctrl = GetControl('toggle')
if ctrl: printText('Toggle: ' + str(ctrl.IsSelected()))
def onDatePicker(event):
ctrl = GetControl('datepicker')
if ctrl: printText('Date: ' + str(ctrl.GetValue()))
def onSlider(event):
ctrl = GetControl('slider')
if ctrl: printText('Slider: ' + str(ctrl.GetValue()))
def onTreeView(event):
ctrl = GetControl('tree')
if ctrl: printText('Treeview: ' + str(ctrl.GetSelectedItemPath('/')))
def onRun(event):
text = GetControl('textfile')
print(text.GetValue())
if text:
rv, out = Execute(text.GetValue())
textarea = GetControl('textarea')
textarea.SetValue(str(rv) + '\n' + out)
progress_value = 0
def threadHandler():
global progress_value
import time
label = GetControl('status')
for i in range(100):
progress_value += 1
RunLater(label.ctrl, lambda : label.SetValue(str(i)))
time.sleep(0.1)
def taskHandler():
import time
prog = GetControl('progress')
for i in range(100):
RunLater(prog.ctrl, lambda : prog.SetValue(i))
time.sleep(0.1)
def timerHandler(event):
global progress_value
print(progress_value)
def onFileDrop(files):
print('onFileDrop',files)
ctrl = GetControl('textfile')
ctrl.SetValue(files[0])
def onTableDrop(files):
print('onFileDrop',files)
ctrl = GetControl('textfile')
ctrl.SetValue(files[0])
def onCreated():
#SetFileDropHandler(GetControl('textfile').ctrl,onFileDrop)
listview = GetControl('table')
listview.AddItem( { "Name":"Anny" , "Age":"18" } )
listview.AddItem( { "Name":"Bobby", "Age":"16" } )
listview.AddItem( { "Name":"Candy", "Age":"14" } )
tree = GetControl('tree')
item = tree.AddRootItem("Item1")
tree.AddItem("Item1-1",item)
tree.AddItem("Item1-2",item)
item = tree.AddRootItem("Item2")
tree.AddItem("Item2-1",item)
tree.AddItem("Item2-2",item)
StartTimer(timerHandler,1000)
StartThread(threadHandler)
StartTask(taskHandler)
def onClosing(event):
if not WpfYesNoDialog("Do you want to quie ?","Quit"):
event.args.Cancel = True
def onOK(event):
win = MakeWindow()
win.Popup()
app_mainmenu = [
{ 'name' : "File",
'item' : [
{ 'name' : "Exit" , 'item' : onExit, 'image' : 'icon/folder512.png', 'tooltip' : 'Exit Program' },
{ 'name' : "-" , },
{ 'name' : "About" , 'item' : onAbout, 'image' : 'exit.png' } ]
}, { 'name' : "Help",
'item' : [
{ 'name' : "About", 'item' : onAbout, 'check' : True, 'image' : 'new.png' } ]
}]
app_tool = [[
{ "name" : "Button", "label" : "Click", "image" : "./icon/folder512.png", 'size' : 16 },
],[
{ "name" : "ChoiceBox", "items" : [ "apple", "grape" ], 'key' : 'choicetool', 'handler' : onChoice },
{ "name" : "ComboBox", "items" : [ "apple", "grape" ] },
{ "name" : "Label", "label" : "Address:", "menu" : app_mainmenu },
{ "name" : "TextField", "key" : "textfile", 'width' : 40 },
{ "name" : "Button", 'handler' : onBrowse, "label" : "Browse", "tooltip" : "About this program" },
{ "name" : "ToggleButton", "label" : "Toggle", 'key' : 'toggle', 'handler' : onToggle },
],
]
app_status = [
{ "name" : "ProgressBar", 'key' : 'progress' },
{ "name" : "Slider", 'key' : 'slider', 'handler' : onSlider },
{ "name" : "Label", "label" : "Ready", 'key' : 'status' },
{ "name" : "Button", "label" : "Click" },
]
tab1 = [[ { "name" : "WebView", "key" : "webview", "expand" : True, "toolbar" : True, "uri" : "http://google.co.kr" },
{ 'expand' : True } ]]
tab2 = [[ { "name" : "ListBox", "items" : [ "apple", "grape" ], 'expand' : True, 'key' : 'listbox', 'handler' : onListBox },
{ 'expand' : True } ]]
tab3 = [[ { "name" : "TableView", "columns" : [ "Name", "Age" ], 'widths' : [ 100, 200 ], 'expand' : True, 'key' : 'table', 'handler' : onListView, 'menu' : app_mainmenu, 'drop' : onTableDrop },
{ 'expand' : True } ]]
tab4 = [[ { "name" : "TreeView", "key" : "tree", 'handler' : onTreeView,"expand" : True },
{ "expand" : True }, ]]
tab5 = [[ { "name" : "ImageView", 'image' : "Lenna.png", "stretch" : "uniform", "scroll" : True, "expand" : True },
{ "expand" : True }, ]]
split1 = [[
{ "name" : "TabPane", "labels" : [ "Web", "List", "Table", "Tree", "Image" ], "items" : [ tab1, tab2, tab3, tab4, tab5 ], "expand" : True },
{ "expand" : True }, ]]
split2 = [[ { "name" : "TextArea", 'key' : 'textarea', "expand" : True, 'toolbar' : True },
{ "expand" : True }, ]]
app_content = [ # vbox
[ # hbox
{ "name" : "GroupBox" , 'label': "Tool2", 'item' : [[
{ "name" : "Label", "label" : "Address:", "menu" : app_mainmenu },
{ "name" : "TextField", "key" : "textfile", "expand" : True, "menu" : app_mainmenu },
{ "name" : "Button", 'handler' : onBrowse, "label" : "File", "tooltip" : "About this program" },
{ "name" : "Button", 'handler' : onBrowseFolder, "label" : "Folder", "tooltip" : "About this program" },
{ "name" : "Button", 'handler' : onRun, "label" : "Run", "tooltip" : "Execute Command" },
]], 'expand' : True }
],
[ # hbox
{ "name" : "ChoiceBox", "items" : [ "apple", "grape" ], 'key' : 'choice', 'handler' : onChoice },
{ "name" : "ComboBox", "items" : [ "apple", "grape" ] },
{ "name" : "CheckBox", "label" : "Click Me", 'key' : 'check', 'handler' : onCheck },
{ "name" : "ToggleButton", "label" : "Toggle", 'key' : 'toggle', 'handler' : onToggle },
{ "name" : "DatePicker", "label" : "Toggle", 'key' : 'datepicker', 'handler' : onDatePicker },
{ 'group' : "Tools" },
],
[ # hbox
{ "name" : "HSplit", "items" : [ split1, split2 ] , "first" : 0.5, "expand" : True, 'border' : False},
{ "expand" : True, 'border' : True },
],
[ # hbox
{ "name" : "Spacer", },
{ "name" : "Button", "label" : "OK", 'width' : 64, 'height' : 24, 'handler' : onOK },
{ "name" : "Spacer", 'width' : 8 },
],
]
def MakeWindow():
win = WpfWindow()
win.SetTitle("PyWPF")
#win.SetIcon("./icon/Lenna.png")
win.SetSize(640,400)
win.SetMenuBar(app_mainmenu)
win.SetToolBar(app_tool)
win.SetStatusBar(app_status)
win.SetContent(app_content)
win.SetCreatedHandler(onCreated)
win.SetCloseHandler(onClosing)
win.SetFileDropHandler(onFileDrop)
return win
if __name__ == "__main__":
global appWin
appWin = MakeWindow()
appWin.Run()