2020년 12월 5일 토요일

[IronPython] WPF Library


WPF Library

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 *
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 *
from System.Windows.Ink import Stroke
from Microsoft.Win32 import ( OpenFileDialog, SaveFileDialog )

import icon

#
# API
#

def RunLater(ctrl,handler):
    ctrl.Dispatcher.BeginInvoke(System.Action(handler)) 

class Class:
    def __init__(self,**kwargs): self.__dict__.update(kwargs)
    
def GetHandler(handler):
    return lambda s,e: handler(Class(sender=s,event=e))
    '''
    def Handler(sender,args):
        handler(Class(sender=sender,args=args))
    return Handler
    '''
    
def StartTimer(handler,msec):
    tmr = System.Timers.Timer(msec)
    tmr.Elapsed += handler
    tmr.AutoReset = True
    #tmr.Enabled = True
    tmr.Start()
    #tmr.Stop();
    #tmr.Dispose();
    
def StartTask(handler):
    Task.Factory.StartNew(handler) 

def Delay(msec):
    #Thread.Sleep() make GUI stuck
    ThisMoment = DateTime.Now;
    duration = TimeSpan(0, 0, 0, 0, msec);
    AfterWards = ThisMoment.Add(duration);
    while AfterWards >= ThisMoment:
        System.Windows.Forms.Application.DoEvents()
        ThisMoment = DateTime.Now
    return DateTime.Now;

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)
       
#
# Controls
#

class WpfCtrl():
    def init(self):
        self.ctrl.Margin  = Thickness(5)
        self.ctrl.Padding = Thickness(1)
    def enable(): self.ctrl.IsEnabled = True
    def disable(): self.ctrl.IsEnabled = False
    def show(): self.ctrl.Visibility = Visibility.Visible
    def hide(): self.ctrl.Visibility = Visibility.Hidden
    def remove(): self.ctrl.Visibility = Visibility.Collapsed
    def is_shown(): return self.ctrl.IsVisible
    def set_width(self,v): self.ctrl.Width = v
    def set_height(self,v): self.ctrl.Height = v
    def set_margin(self,l,t,r,b): self.ctrl.Margin = System.Windows.Thickness(l,t,r,b)
    def shadow_effect(self):
        from System.Windows.Media.Effects import DropShadowBitmapEffect
        self.ctrl.BitmapEffect = DropShadowBitmapEffect()
    def set_fontsize(self,size):
        self.ctrl.FontSize = size
    def set_tooltip(self,tooltip):
        tip = ToolTip()
        tip.Content = tooltip
        self.ctrl.ToolTip = tip
    def set_menu(self,menu_table):
        menu = ContextMenu()
        for m in menu_table:
            menu.Items.Add(WpfMenu(m['name'],m['item']).ctrl)         
        self.ctrl.ContextMenu = menu
    def set_filedrop(self,handler):
        SetFileDropHandler(self.ctrl,handler)
        
class WpfButton(WpfCtrl):
    def __init__(self,text=None,handler=None,image=None,size=None,vert=True,**kwargs):
        self.ctrl = Button()
        self.init(**kwargs)
        stack = StackPanel()
        if vert: stack.Orientation = Orientation.Vertical
        else: stack.Orientation = Orientation.Horizontal
        self.ctrl.Content = stack
        if image:
            img = Image()
            img.Source = BitmapImage(System.Uri(image,System.UriKind.Relative))
            img.VerticalAlignment = VerticalAlignment.Center
            img.Stretch = Stretch.Fill #Stretch.None
            if size: img.Width = size; img.Height = size
            stack.Children.Add(img)
        if text: 
            txt = TextBlock()
            txt.Text = text
            txt.TextAlignment = TextAlignment.Center
            stack.Children.Add(txt)         
        if handler: self.ctrl.Click += handler
    
class WpfCheck(WpfCtrl):
    def __init__(self,text=None,handler=None,**kwargs):
        self.ctrl = CheckBox()
        self.ctrl.VerticalAlignment = VerticalAlignment.Center
        self.ctrl.VerticalContentAlignment = VerticalAlignment.Center
        self.init(**kwargs)
        if text: self.ctrl.Content = text
        if handler: self.ctrl.Click += handler        
    def get_value(self): return self.ctrl.IsChecked
    def GetSelectedItem(self): return self.ctrl.SelectedItem

class WpfChoice(WpfCtrl):
    def __init__(self,handler=None,items=None,selected=0,**kwargs):
        self.ctrl = ComboBox()
        self.init(**kwargs)
        if handler: self.ctrl.SelectionChanged += handler
        if items:
            self.ctrl.ItemsSource = items
            self.ctrl.SelectedIndex = selected     
    def get_value(self): return self.ctrl.Text
    def get_added_item(self,args): return args.AddedItems[0]
    def get_selected_item(self): return self.ctrl.SelectedItem
    def get_selected_text(self): return self.ctrl.SelectedItem.ToString()
    
class WpfCombo(WpfCtrl):
    def __init__(self,handler=None,items=None,selected=0,**kwargs):
        self.ctrl = ComboBox()
        self.ctrl.IsEditable=True
        self.ctrl.IsReadOnly=False        
        self.init(**kwargs)
        if handler: self.ctrl.SelectionChanged += handler
        if items:
            self.ctrl.ItemsSource = items
            self.ctrl.SelectedIndex = selected     
    def get_value(self): return self.ctrl.Text
    def get_added_item(self,args): return args.AddedItems[0]
    def get_selected_item(self): return self.ctrl.SelectedItem
    def get_selected_text(self): return self.ctrl.SelectedItem.ToString()

class WpfDate(WpfCtrl):
    def __init__(self,handler=None,**kwargs):   
        self.ctrl = DatePicker()
        self.init(**kwargs)
        if handler: self.ctrl.SelectedDateChanged += handler
    def get_value(self):
        return self.ctrl.Text
    def set_value(self,v):
        self.ctrl.Text = v

class WpfEdit(WpfCtrl):
    def __init__(self,text=None,multiline=True,tool=False,handler=None,image=None,size=None,vert=True,**kwargs):
        self.text = TextBox()
        self.ctrl = self.text
        self.init(**kwargs)
        if 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 handler: self.ctrl.Click += handler
        if tool:
            self.vbox = vbox.WpfVBox()
            self.hbox = hbox.WpfHBox()
            self.hbox.add_item(self.get_button("Clear", self.clear_handler))
            self.hbox.add_item(self.get_button("Copy", self.copy_handler))
            self.hbox.add_item(self.get_button("CopyAll", self.copy_all_handler))
            self.hbox.add_item(self.get_button("Paste", self.paste_handler))
            self.hbox.add_item(self.get_button("PasteHtml", self.paste_html_handler))
            self.vbox.add_item(self.hbox.ctrl)
            self.vbox.add_item(self.text,expand=True)
            self.ctrl = self.vbox.ctrl

    def clear(self):
        self.text.Text = ""
    def get_value(self):
        return self.text.Text
    def set_value(self,text):
        self.text.Text = text
    def append_text(self,text):
        self.text.Text += text
    def set_width(self,width):
        self.text.Width = width
    def scroll_to_end(self):
        self.text.ScrollToEnd()
    def set_wrap(self,wrap):
        self.text.TextWrapping = TextWrapping.Wrap if wrap else TextWrapping.NoWrap

    def get_button(self,label,handler):
        b = Button()
        b.Content = label
        b.Click += handler
        return b
    def clear_handler(self,sender,args):
        self.text.Clear()
    def copy_handler(self,sender,args):
        self.text.Copy()
    def copy_all_handler(self,sender,args):
        self.text.SelectAll()
        self.text.Copy()
    def paste_handler(self,sender,args):
        self.text.Paste()
    def paste_html_handler(self,sender,args):
        self.text.Text = ClipboardGetHtmlData()
        
class WpfGroup(WpfCtrl):
    def __init__(self,text=None):
        self.ctrl = GroupBox()
        if text: self.ctrl.Header = text
    def add_item(self,item):
        self.ctrl.AddChild(item)
 
class WpfImage(WpfCtrl):
    def __init__(self,imagefile,stretch=None,scroll=True,multiple=False,**kwargs):
        self.ctrl = Label()
        self.init(**kwargs)
        self.image = Image()
        self.image.HorizontalAlignment = HorizontalAlignment.Center
        self.image.VerticalAlignment = VerticalAlignment.Center
        if imagefile: self.image.Source = BitmapImage(System.Uri(imagefile,System.UriKind.Relative))
        if stretch: self.stretch(stretch)
        else: self.StretchUniform()
        '''if size: 
            self.image.Height = float(size); 
            self.image.Width = float(size)'''
        if scroll:
            scroll = ScrollViewer()
            scroll.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto
            scroll.Content = self.image
            self.ctrl.Content = scroll
        elif multiple:
            stack = StackPanel()
            stack.Orientation = Orientation.Horizontal
            stack.Children.Add(self.image)
            self.ctrl.Content = stack 
        else:
            self.ctrl.Content = self.image       
    def stretch_none(self): self.image.Stretch = Stretch.None
    def stretch_fill(self): self.image.Stretch = Stretch.Fill
    def stretch_uniform(self): self.image.Stretch = Stretch.Uniform
    def stretch_uniform_to_fill(self): self.image.Stretch = Stretch.UniformToFill
    def stretch(self,stretch):
        if stretch == 'none': self.stretch_none()
        elif stretch == 'fill': self.stretch_fill()
        elif stretch == 'uniform': self.stretch_uniform()
        elif stretch == 'uniformfill': self.stretch_uniform_to_fill()

class WpfLabel(WpfCtrl):
    def __init__(self,text=None,background=None,**kwargs):
        self.ctrl = Label()
        self.init(**kwargs)
        if text: self.ctrl.Content = text
        if background: self.ctrl.Background = background
        self.ctrl.HorizontalAlignment = HorizontalAlignment.Stretch
        self.ctrl.VerticalAlignment = VerticalAlignment.Center   

class WpfList(WpfCtrl):
    def __init__(self,handler=None,items=None,selected=0,**kwargs):
        self.ctrl = ListBox()
        self.init(**kwargs)
        if handler: self.ctrl.SelectionChanged += handler
        if items:
            self.ctrl.ItemsSource = items
            self.ctrl.SelectedIndex = selected     
    def get_value(self): return self.get_selected_text()
    def get_selected_item(self): return self.ctrl.SelectedItem
    def get_selected_text(self): return self.ctrl.SelectedItem.ToString()

class WpfProgress(WpfCtrl):
    def __init__(self,**kwargs): 
        self.ctrl = ProgressBar()
        #self.ctrl.IsIndeterminate = True
        #self.ctrl.Margin = new Thickness(10,0,10,10);
        self.init(**kwargs)
        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
    def get_value(self):
        return self.ctrl.Value
    def set_value(self,v):
        self.ctrl.Value = v

class WpfSlider(WpfCtrl):
    def __init__(self,handler=None,min=None,max=None,value=None,**kwargs):   
        self.ctrl = Slider()
        self.init(**kwargs)
        if handler: self.ctrl.ValueChanged += handler
        self.ctrl.Width = 100;
        self.ctrl.Height = 16;        
        self.ctrl.Minimum = min if min else 0
        self.ctrl.Maximum = max if max else 100     
        self.ctrl.Value = value if value else 0
        self.ctrl.SmallChange = 1
        self.ctrl.LargeChange = 10
        self.ctrl.TickPlacement = TickPlacement.BottomRight
        self.ctrl.TickFrequency = 10
    def get_value(self):
        return self.ctrl.Value
    def set_value(self,v):
        self.ctrl.Value = v
           
class WpfTable(WpfCtrl):
    def __init__(self,handler=None,columns=None,widths=None,**kwargs):
        self.ctrl = ListView()
        self.table = DataTable('table')
        self.cols = []
        self.init(**kwargs)
        if handler: self.ctrl.SelectionChanged += handler
        self.grid = GridView()
        self.grid.AllowsColumnReorder = True; 
        self.grid.ColumnHeaderToolTip = "ListView Column Info";     
        if columns: 
            for i in range(0,len(columns)):
                width = widths[i] if widths else None
                self.add_column(columns[i],width)     
        self.ctrl.View = self.grid
        self.ctrl.ItemsSource = self.table.DefaultView #DataView(self.table)
        self.ctrl.AddHandler(GridViewColumnHeader.ClickEvent, RoutedEventHandler(self.OnColumnHeaderClick))
        self.sort_dir = ListSortDirection.Ascending

    def clear(self):
        #k = self.table.Rows.IndexOf(item)
        for k in range(len(self.table.Rows),0,-1):
            self.table.Rows[k-1].Delete() 
        self.table.AcceptChanges()  #RejectChanges()
    def add_column(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)
        self.cols.append(name)
    def add_row(self,row):
        if len(self.cols) == len(row):
            item = self.table.NewRow()
            for index in range(len(row)):
                item[self.cols[index]] = row[index]
            self.table.Rows.Add(item)        
    def add_item(self,items):
        item = self.table.NewRow()
        if type(items) == dict:
            for key, value in items.items(): item[key] = value;
        else: 
            for i in range(len(items)): item[i] = items[i];
        self.table.Rows.Add(item);
    def get_value(self): 
        return self.ctrl.SelectedItem
    def get_selected_items_org(self): 
        return self.ctrl.SelectedItems
    def get_selected_items(self): 
        items = []
        for row in self.ctrl.SelectedItems:
            item = []
            for col in self.cols:
                item.append(row[col])
            items.append(item)
        return items
    def get_all_items(self): 
        items = []
        for row in self.ctrl.Items:
            item = []
            for col in self.cols:
                item.append(row[col])
            items.append(item)
        return items     
    def get_column_items(self,col): 
        items = []
        for row in self.ctrl.Items:
            items.append(row[col])
        return items  
    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 column_sort(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.column_sort( columnBinding.Path.Path, self.sort_dir ) #headerClicked.Column.Header

class WpfToggle(WpfCtrl):
    def __init__(self,text=None,handler=None,image=None,size=None,vert=True,**kwargs):
        self.ctrl = ToggleButton()
        self.init(**kwargs)
        stack = StackPanel()
        if vert: stack.Orientation = Orientation.Vertical
        else: stack.Orientation = Orientation.Horizontal
        self.ctrl.Content = stack
        if image:
            img = Image()
            img.Source = BitmapImage(System.Uri(image,System.UriKind.Relative))
            img.VerticalAlignment = VerticalAlignment.Center
            img.Stretch = Stretch.Fill #Stretch.None
            if size: img.Width = size; img.Height = size
            stack.Children.Add(img)
        if text: 
            txt = TextBlock()
            txt.Text = text
            txt.TextAlignment = TextAlignment.Center
            stack.Children.Add(txt)         
        if handler: self.ctrl.Click += handler
    def get_value(self): return self.ctrl.IsChecked    

class WpfTree(WpfCtrl):
    def __init__(self,name="root",handler=None,**kwargs):
        self.root = TreeViewItem()
        self.root.Header = name
        self.root.IsExpanded = True
        self.ctrl = TreeView()
        self.ctrl.Items.Add(self.root)
        self.init(**kwargs)
        if handler: self.ctrl.SelectedItemChanged  += handler
    def add_root_item(self,label):
        return self.add_item(label)
    def add_item(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 get_selected_item(self):
        return self.ctrl.SelectedItem
    def get_selected_item_text(self):
        return self.ctrl.SelectedItem.Header.ToString()
    def get_selected_item_path(self,delim=""):
        item = self.ctrl.SelectedItem
        return self.get_item_path(item,delim)
    def get_item_path(self,item,delim=""):
        path = item.Header.ToString()
        while type(item.Parent) == TreeViewItem:
            item = item.Parent
            path = item.Header.ToString() + delim + path
        return path
    def get_parent_item(self,item):
        return item.Parent
    def get_item_value(self,item):
        return item.Header.ToString()

class WpfWeb():
    def __init__(self,url=None,tool=False):
        self.web = WebBrowser()
        self.ctrl = self.web
        self.web.Navigated += self.loaded_hndler
        if tool:
            self.vbox = vbox.WpfVBox()
            self.hbox = hbox.WpfHBox()
            self.text = TextBox()
            self.hbox.add_item(self.button("<-", self.back_handler))
            self.hbox.add_item(self.button("->", self.forward_handler))
            self.hbox.add_item(self.button("<>", self.refresh_handler))
            self.hbox.add_item(self.text, {'expand':True})
            self.hbox.add_item(self.button("Go", self.go_Handler))
            self.vbox.add_item(self.hbox.ctrl)
            self.vbox.add_item(self.web,expand=True)
            self.ctrl = self.vbox.ctrl
        if url: self.go(url)
    def button(self,label,handler): b = Button(); b.Content = label; b.Click += handler; return b
    def loaded_hndler(self,sender,args): self.text.Text = self.web.Source.ToString()
    def go_Handler(self,sender,args):
        uri = self.text.Text
        if not uri.startswith('http'): uri = "http://" + uri; self.text.Text = uri
        self.Go(uri)
    def back_handler(self,sender,args): self.back()
    def forward_handler(self,sender,args): self.forward()
    def refresh_handler(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
       
#
# Containers
#

class WpfLayout():
    def add_separater(self,parent=None):
        self.add_item(Separator())
    def add_label(self,text):
        label = Label()
        label.Content = text
        self.add_item( label )    
    def add_button(self,text,handler=None):
        button = Button()
        button.Content = text
        if handler: button.Click += handler
        self.add_item( button )   
        
class WpfGrid():
    def __init__(self,row=None,col=None):
        self.ctrl = Grid()
    def add_row(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 add_column(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 add_item(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 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 = Thickness(2)
        #self.ctrl.Content = self.grid
    def add_row(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 add_column(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 add_item(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 WpfHBox(WpfLayout):
    def __init__(self):
        self.ctrl = Grid()
        self.ctrl.Margin = Thickness(1)
        self.cols = 0
        
    def add_item(self,item,expand=False,group=None,border=False,width=1):
        if 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 group:
            gbox = GroupBox()
            gbox.Header = group
            gbox.AddChild(item)
            Grid.SetColumn(gbox, self.cols);
            self.ctrl.Children.Add(gbox)
        else:
            if 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 add_splitter(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

    def add_spacer(self):
        self.add_item( Label(), expand=True )
        
class WpfHSplit():
    def __init__(self,lsize=1,rsize=1):
        self.box = hbox.WpfHBox()
        self.ctrl = self.box.ctrl
        self.box.ctrl.Margin = Thickness(1)
        self.widths = [ lsize, rsize ]
    def add_items(self,items,widths=None):
        if not widths: widths = self.widths
        self.box.add_item(items[0],width=widths[0],expand=True)
        self.box.add_splitter()
        self.box.add_item(items[1],width=widths[1],expand=True)

class WpfTab():
    def __init__(self,items=None):
        self.ctrl = TabControl()
        self.ctrl.Margin =  System.Windows.Thickness(15)
        if items and type(items) == dict:
            for k,v in items.items(): self.add_item( k, v) 
    def add_item(self,label,ctrl):
        tab = TabItem()
        tab.Header = label
        tab.Content = ctrl
        self.ctrl.Items.Add(tab)

class WpfVBox(WpfLayout):
    def __init__(self):
        self.ctrl = Grid()
        self.ctrl.Margin = Thickness(1)
        self.rows = 0
        
    def add_item(self,item,expand=False,border=False,group=None,height=1):
        if 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 group:
            gbox = GroupBox()
            gbox.Header = group
            gbox.AddChild(item)
            Grid.SetRow(gbox, self.rows);
            self.ctrl.Children.Add(gbox)
        else:
            if 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 add_splitter(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
          
    def add_spacer(self):
        self.add_item( Label(), expand=True )

class WpfHSplit():
    def __init__(self,lsize=1,rsize=1):
        self.box = vbox.WpfVBox()
        self.ctrl = self.box.ctrl
        self.box.ctrl.Margin = Thickness(1)
        self.heights = [ lsize, rsize ]
    def add_items(self,items,heights=None):
        if not heights: heights = self.heights
        self.box.add_item(items[0],height=heights[0],expand=True)
        self.box.add_splitter()
        self.box.add_item(items[1],height=heights[1],expand=True)
                    
#
# Dialogs
#

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[0]

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 

#
# Windows
#

class WpfMenuBar():
    def __init__(self):
        self.ctrl = Menu()
        self.ctrl.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch
        self.ctrl.VerticalAlignment = System.Windows.VerticalAlignment.Top
        
    def add_separater(self,parent=None):
        self.menu.Items.Add(Separator())
        
    def add_menu(self,name,parent=None):
        self.menu = MenuItem()
        self.menu.Header = name; 
        if not parent: parent = self.ctrl
        parent.Items.Add(self.menu)
        return self.menu
        
    def add_item(self,name,handler=None,icon=None,iconfile=None,tooltip=None,parent=None):
        item = MenuItem()
        if name: item.Header = name; 
        if handler: item.Click += handler
        if icon: image = Image(); image.Source = icon; item.Icon = image
        if iconfile: image = Image(); image.Source = self.get_imagefile(iconfile); item.Icon = image
        if tooltip: tip = ToolTip(); tip.Content = tooltip; item.ToolTip = tip
        if not parent: parent = self.menu
        parent.Items.Add(item)
        return item
        
    def get_imagefile(self,filename):
        return BitmapImage(System.Uri(filename,System.UriKind.Relative))

class WpfStatusBar():
    def __init__(self):
        self.ctrl = StatusBar()
        self.ctrl.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
        self.ctrl.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;        
    def add_item(self,ctrl):
        item = StatusBarItem()
        item.Content = ctrl   
        self.ctrl.Items.Add(item)
    def add_separater(self,parent=None):
        self.ctrl.Items.Add(Separator())  
    def add_label(self,text):
        label = Label()
        label.Content = text
        self.add_item( label )    
    def add_button(self,text,handler=None):
        button = Button()
        button.Content = text
        if handler: button.Click += handler
        self.add_item( button )    

class WpfToolBar():
    def __init__(self):
        self.ctrl = ToolBarTray()
    def add_toolbar(self,parent=None):
        self.tool = ToolBar()
        self.tool.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
        self.tool.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
        if not parent: parent = self.ctrl
        parent.AddChild(self.tool)
    def add_item(self,ctrl,handler=None,icon=None,tooltip=None,parent=None):
        if handler: ctrl.Click += handler
        if icon: image = Image(); image.Source = self.get_image(icon); ctrl.Icon = image
        if tooltip: tip = ToolTip(); tip.Content = tooltip; ctrl.ToolTip = tip
        if not parent: parent = self.tool
        parent.Items.Add(ctrl)
    def add_separater(self,parent=None):
        if not parent: parent = self.tool
        parent.Items.Add(Separator())
    def get_image(self,filename):
        return BitmapImage(System.Uri(filename,System.UriKind.Relative))

class Win(Window):
    def __init__(self,title=None,width=None,height=None):
        self.Closing += self.on_close
        if title: self.Title = title
        if width: self.Width = width
        if height:self.Height= height
        self.vbox = WpfVBox()
        self.Content = self.vbox.ctrl
        self.menubar = None
        self.toolbar = None
        self.statusbar = None
        self.content = None
    def set_title(self,title):  self.Title = title
    def set_icon(self,image): self.Icon = image
    def set_iconfile(self,imagefile): self.Icon = self.get_imagefile(imagefile)
    def set_width(self,width): self.Width = width
    def set_height(self,height): self.Height = height
    def set_size(self,width,height): self.Width = width; self.Height = height
    def set_content(self,content):  self.content = content
    def add_menubar(self,menu): self.menubar = menu        
    def add_toolbar(self,tool): self.toolbar = tool       
    def add_statusbar(self,status): self.statusbar = status
    def run(self): 
        if self.menubar: self.vbox.add_item(self.menubar,expand=False)    
        if self.toolbar: self.vbox.add_item(self.toolbar,expand=False)    
        if self.content: self.vbox.add_item(self.content,expand=True)    
        if self.statusbar: self.vbox.add_item(self.statusbar,expand=False)    
        self.Show(); 
        Application().Run(self) 
    def close(self): self.Close()
    def on_close(self,sender,event):
    	rv = MessageBox.Show("Do you want to close ?", "Warning", MessageBoxButton.YesNo )
    	if rv == MessageBoxResult.Yes:
    		event.Cancel = False
    	else:
    		event.Cancel = True
    def get_imagefile(self,filename):
        return icon.GetBitmapFrameFromFile(filename)

if __name__ == "__main__":
    import icon as ic

    def setMenuBar():
        m = WpfMenuBar()
        m.add_menu("File");
        m.add_item("Exit", lambda s,e: app.Close())
        m.add_separater()
        m.add_item("Exit", icon=ic.GetExitBitmapImage(), handler=lambda s,e: app.Close())
        app.add_menubar(m.ctrl)

    def setToolBar():
        t = WpfToolBar()
        t.add_toolbar();
        button = Button()
        button.Content = "Exit"
        button.Click += lambda s,e: app.Close()
        t.add_item(button)
        t.add_separater()
        
        stack = StackPanel()
        img = Image()
        img.Width = 16
        img.Height = 16
        img.Source = ic.GetExitBitmapImage()
        stack.Children.Add(img)    
        button = Button()
        button.Content = stack
        button.Click += lambda s,e: app.Close()
        t.add_item(button)
        app.add_toolbar(t.ctrl)
                
    def setStatusBar():
        s = WpfStatusBar()
        button = Button()
        button.Content = "Exit"
        button.Click += lambda s,e: app.Close()
        s.add_item(button)

        stack = StackPanel()
        button = Button()
        button.Content = stack
        button.Click += lambda s,e: app.Close()
        img = Image()
        img.Source = ic.GetExitBitmapImage()
        img.Width = 16 
        img.Height = 16
        stack.Children.Add(img)
        s.add_item(button)
        app.add_statusbar(s.ctrl)
        
    def setContent():
        content = Button()
        content.Content = "Content"
        app.set_content(content)
            
    app = Win("Window Demo",320,240)
    app.set_icon(icon.GetExitBitmapImage())
    #app.set_icon(icon.GetBitmapFrameFromFile("exit.png"))
    
    setMenuBar()
    setToolBar()
    setContent()
    setStatusBar()

    app.run()

댓글 없음:

댓글 쓰기