mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-29 06:32:40 -06:00
834 lines
27 KiB
Python
834 lines
27 KiB
Python
#----------------------------------------------------------------------------
|
|
# Name: BrowseImage.py
|
|
# Purpose: Display and Select Image Files
|
|
#
|
|
# Original Author: Lorne White
|
|
#
|
|
# Version: 2.0
|
|
# Date: June 16, 2007
|
|
# Licence: wxWindows license
|
|
# Tags: phoenix-port
|
|
#----------------------------------------------------------------------------
|
|
# 2.0 Release - Bill Baxter (wbaxter@gmail.com)
|
|
# Date: June 16, 2007
|
|
# o Changed to use sizers instead of fixed placement.
|
|
# o Made dialog resizeable
|
|
# o Added a splitter between file list and view pane
|
|
# o Made directory path editable
|
|
# o Added an "up" button" to go to the parent dir
|
|
# o Changed to show directories in file list
|
|
# o Don't select images on double click any more
|
|
# o Added a 'broken image' display for files that wx fails to identify
|
|
# o Redesigned appearance -- using bitmap buttons now, and rearranged things
|
|
# o Fixed display of masked gifs
|
|
# o Fixed zooming logic to show shrunken images at correct aspect ratio
|
|
# o Added different background modes for preview (white/grey/dark/checkered)
|
|
# o Added framing modes for preview (no frame/box frame/tinted border)
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
#
|
|
# 12/08/2003 - Jeff Grimmett (grimmtooth@softhome.net)
|
|
#
|
|
# o Updated for wx namespace
|
|
# o Corrected a nasty bug or two - see comments below.
|
|
# o There was a duplicate ImageView.DrawImage() method. Que?
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
# 1.0 Release - Lorne White
|
|
# Date: January 29, 2002
|
|
# Create list of all available image file types
|
|
# View "All Image" File Types as default filter
|
|
# Sort the file list
|
|
# Use newer "re" function for patterns
|
|
#
|
|
# Tags: phoenix-port, documented, unittest
|
|
#---------------------------------------------------------------------------
|
|
"""
|
|
This module provides the :class:`ImageDialog` which allows to view and select
|
|
an image.
|
|
|
|
|
|
Description
|
|
===========
|
|
|
|
The :class:`ImageDialog` allows the user to view images and select one.
|
|
|
|
Usage
|
|
=====
|
|
|
|
A simple usage would be::
|
|
|
|
import wx
|
|
import wx.lib.mixins.inspection as wit
|
|
import wx.lib.imagebrowser as ib
|
|
|
|
app = wit.InspectableApp()
|
|
|
|
with ib.ImageDialog(None) as dlg:
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
# show the selected file
|
|
print("You Selected File: " + dlg.GetFile())
|
|
else:
|
|
print("You pressed Cancel")
|
|
|
|
app.MainLoop()
|
|
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import wx
|
|
|
|
_ = wx.GetTranslation
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
BAD_IMAGE = -1
|
|
ID_WHITE_BG = wx.NewId()
|
|
ID_BLACK_BG = wx.NewId()
|
|
ID_GREY_BG = wx.NewId()
|
|
ID_CHECK_BG = wx.NewId()
|
|
ID_NO_FRAME = wx.NewId()
|
|
ID_BOX_FRAME = wx.NewId()
|
|
ID_CROP_FRAME = wx.NewId()
|
|
|
|
def ConvertBMP(file_nm):
|
|
"""
|
|
Convert file
|
|
|
|
:param string `file_nm`: path to file
|
|
|
|
:return: :class:`Image` or BAD_IMAGE
|
|
"""
|
|
if file_nm is None:
|
|
return None
|
|
|
|
fl_fld = os.path.splitext(file_nm)
|
|
ext = fl_fld[1]
|
|
ext = ext[1:].lower()
|
|
|
|
# Don't try to create it directly because wx throws up
|
|
# an annoying messasge dialog if the type isn't supported.
|
|
if wx.Image.CanRead(file_nm):
|
|
image = wx.Image(file_nm, wx.BITMAP_TYPE_ANY)
|
|
return image
|
|
|
|
# BAD_IMAGE means a bad image, None just means no image (i.e. directory)
|
|
return BAD_IMAGE
|
|
|
|
|
|
def GetCheckeredBitmap(blocksize=8, ntiles=4, rgb0='\xFF', rgb1='\xCC'):
|
|
"""
|
|
Creates a square RGB checkered bitmap using the two specified colors.
|
|
|
|
The bitmap returned will have width = height = blocksize*ntiles*2
|
|
|
|
:param int `blocksize`: the number of pixels in each solid color square
|
|
:param int `ntiles1`: the number of tiles along width and height. Each tile is 2x2 blocks.
|
|
:param `rbg0`: the first color, as 3-byte strings.
|
|
:param `rgb1`: the second color, as 3-byte strings. If only 1 byte is provided, it is treated as a grey value.
|
|
|
|
:return: :class:`BitmapFromBuffer`
|
|
|
|
"""
|
|
size = blocksize*ntiles*2
|
|
|
|
if len(rgb0)==1:
|
|
rgb0 = rgb0 * 3
|
|
if len(rgb1)==1:
|
|
rgb1 = rgb1 * 3
|
|
|
|
strip0 = (rgb0*blocksize + rgb1*blocksize)*(ntiles*blocksize)
|
|
strip1 = (rgb1*blocksize + rgb0*blocksize)*(ntiles*blocksize)
|
|
band = strip0 + strip1
|
|
data = band * ntiles
|
|
return wx.Bitmap.FromBuffer(size, size, data)
|
|
|
|
def GetNamedBitmap(name):
|
|
return IMG_CATALOG[name].GetBitmap()
|
|
|
|
|
|
class ImageView(wx.Window):
|
|
def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
|
|
style=wx.BORDER_SUNKEN
|
|
):
|
|
wx.Window.__init__(self, parent, id, pos, size, style=style)
|
|
|
|
self.image = None
|
|
|
|
self.check_bmp = None
|
|
self.check_dim_bmp = None
|
|
|
|
# dark_bg is the brush/bitmap to use for painting in the whole background
|
|
# lite_bg is the brush/bitmap/pen to use for painting the image rectangle
|
|
self.dark_bg = None
|
|
self.lite_bg = None
|
|
|
|
self.border_mode = ID_CROP_FRAME
|
|
self.SetBackgroundMode( ID_WHITE_BG )
|
|
self.SetBorderMode( ID_NO_FRAME )
|
|
|
|
# Changed API of wx uses tuples for size and pos now.
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
|
|
self.Bind(wx.EVT_SIZE, self.OnSize)
|
|
|
|
|
|
def SetValue(self, file_nm): # display the selected file in the panel
|
|
image = ConvertBMP(file_nm)
|
|
self.image = image
|
|
self.Refresh()
|
|
|
|
def SetBackgroundMode(self, mode):
|
|
self.bg_mode = mode
|
|
self._updateBGInfo()
|
|
|
|
def _updateBGInfo(self):
|
|
bg = self.bg_mode
|
|
border = self.border_mode
|
|
|
|
self.dark_bg = None
|
|
self.lite_bg = None
|
|
|
|
if border == ID_BOX_FRAME:
|
|
self.lite_bg = wx.BLACK_PEN
|
|
|
|
if bg == ID_WHITE_BG:
|
|
if border == ID_CROP_FRAME:
|
|
self.SetBackgroundColour('LIGHT GREY')
|
|
self.lite_bg = wx.WHITE_BRUSH
|
|
else:
|
|
self.SetBackgroundColour('WHITE')
|
|
|
|
elif bg == ID_GREY_BG:
|
|
if border == ID_CROP_FRAME:
|
|
self.SetBackgroundColour('GREY')
|
|
self.lite_bg = wx.LIGHT_GREY_BRUSH
|
|
else:
|
|
self.SetBackgroundColour('LIGHT GREY')
|
|
|
|
elif bg == ID_BLACK_BG:
|
|
if border == ID_BOX_FRAME:
|
|
self.lite_bg = wx.WHITE_PEN
|
|
if border == ID_CROP_FRAME:
|
|
self.SetBackgroundColour('GREY')
|
|
self.lite_bg = wx.BLACK_BRUSH
|
|
else:
|
|
self.SetBackgroundColour('BLACK')
|
|
|
|
else:
|
|
if self.check_bmp is None:
|
|
self.check_bmp = GetCheckeredBitmap()
|
|
self.check_dim_bmp = GetCheckeredBitmap(rgb0='\x7F', rgb1='\x66')
|
|
if border == ID_CROP_FRAME:
|
|
self.dark_bg = self.check_dim_bmp
|
|
self.lite_bg = self.check_bmp
|
|
else:
|
|
self.dark_bg = self.check_bmp
|
|
|
|
self.Refresh()
|
|
|
|
def SetBorderMode(self, mode):
|
|
self.border_mode = mode
|
|
self._updateBGInfo()
|
|
|
|
def OnSize(self, event):
|
|
event.Skip()
|
|
self.Refresh()
|
|
|
|
def OnPaint(self, event):
|
|
dc = wx.PaintDC(self)
|
|
self.DrawImage(dc)
|
|
|
|
def OnEraseBackground(self, evt):
|
|
if self.bg_mode != ID_CHECK_BG:
|
|
evt.Skip()
|
|
return
|
|
dc = evt.GetDC()
|
|
if dc:
|
|
self.PaintBackground(dc, self.dark_bg)
|
|
|
|
def PaintBackground(self, dc, painter, rect=None):
|
|
if painter is None:
|
|
return
|
|
if rect is None:
|
|
pos = self.GetPosition()
|
|
sz = self.GetSize()
|
|
else:
|
|
pos = rect.Position
|
|
sz = rect.Size
|
|
|
|
if type(painter)==wx.Brush:
|
|
dc.SetPen(wx.TRANSPARENT_PEN)
|
|
dc.SetBrush(painter)
|
|
dc.DrawRectangle(pos.x,pos.y,sz.width,sz.height)
|
|
elif type(painter)==wx.Pen:
|
|
dc.SetPen(painter)
|
|
dc.SetBrush(wx.TRANSPARENT_BRUSH)
|
|
dc.DrawRectangle(pos.x-1,pos.y-1,sz.width+2,sz.height+2)
|
|
else:
|
|
self.TileBackground(dc, painter, pos.x,pos.y,sz.width,sz.height)
|
|
|
|
|
|
def TileBackground(self, dc, bmp, x,y,w,h):
|
|
"""Tile bmp into the specified rectangle"""
|
|
bw = bmp.GetWidth()
|
|
bh = bmp.GetHeight()
|
|
|
|
dc.SetClippingRegion(x,y,w,h)
|
|
|
|
# adjust so 0,0 so we always match with a tiling starting at 0,0
|
|
dx = x % bw
|
|
x = x - dx
|
|
w = w + dx
|
|
|
|
dy = y % bh
|
|
y = y - dy
|
|
h = h + dy
|
|
|
|
tx = x
|
|
x2 = x+w
|
|
y2 = y+h
|
|
|
|
while tx < x2:
|
|
ty = y
|
|
while ty < y2:
|
|
dc.DrawBitmap(bmp, tx, ty)
|
|
ty += bh
|
|
tx += bw
|
|
|
|
def DrawImage(self, dc):
|
|
|
|
if not hasattr(self,'image') or self.image is None:
|
|
return
|
|
|
|
wwidth,wheight = self.GetSize()
|
|
image = self.image
|
|
bmp = None
|
|
if image != BAD_IMAGE and image.IsOk():
|
|
iwidth = image.GetWidth() # dimensions of image file
|
|
iheight = image.GetHeight()
|
|
else:
|
|
bmp = wx.ArtProvider.GetBitmap(wx.ART_MISSING_IMAGE, wx.ART_MESSAGE_BOX, (64,64))
|
|
iwidth = bmp.GetWidth()
|
|
iheight = bmp.GetHeight()
|
|
|
|
# squeeze iwidth x iheight image into window, preserving aspect ratio
|
|
|
|
xfactor = float(wwidth) / iwidth
|
|
yfactor = float(wheight) / iheight
|
|
|
|
if xfactor < 1.0 and xfactor < yfactor:
|
|
scale = xfactor
|
|
elif yfactor < 1.0 and yfactor < xfactor:
|
|
scale = yfactor
|
|
else:
|
|
scale = 1.0
|
|
|
|
owidth = int(scale*iwidth)
|
|
oheight = int(scale*iheight)
|
|
|
|
diffx = (wwidth - owidth)/2 # center calc
|
|
diffy = (wheight - oheight)/2 # center calc
|
|
|
|
if not bmp:
|
|
if owidth!=iwidth or oheight!=iheight:
|
|
sc_image = sc_image = image.Scale(owidth,oheight)
|
|
else:
|
|
sc_image = image
|
|
bmp = sc_image.ConvertToBitmap()
|
|
|
|
if image != BAD_IMAGE and image.IsOk():
|
|
self.PaintBackground(dc, self.lite_bg, wx.Rect(diffx,diffy,owidth,oheight))
|
|
|
|
dc.DrawBitmap(bmp, diffx, diffy, useMask=True) # draw the image to window
|
|
|
|
|
|
class ImagePanel(wx.Panel):
|
|
def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
|
|
style=wx.NO_BORDER
|
|
):
|
|
wx.Panel.__init__(self, parent, id, pos, size, style=style)
|
|
|
|
vbox = wx.BoxSizer(wx.VERTICAL)
|
|
self.SetSizer(vbox)
|
|
|
|
self.view = ImageView(self)
|
|
vbox.Add(self.view, 1, wx.GROW|wx.ALL, 0)
|
|
|
|
hbox_ctrls = wx.BoxSizer(wx.HORIZONTAL)
|
|
vbox.Add(hbox_ctrls, 0, wx.ALIGN_RIGHT|wx.TOP, 4)
|
|
|
|
bmp = GetNamedBitmap('White')
|
|
btn = wx.BitmapButton(self, ID_WHITE_BG, bmp, style=wx.BU_EXACTFIT)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
|
|
btn.SetToolTip(_("Set background to white"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
bmp = GetNamedBitmap('Grey')
|
|
btn = wx.BitmapButton(self, ID_GREY_BG, bmp, style=wx.BU_EXACTFIT)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
|
|
btn.SetToolTip(_("Set background to grey"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
bmp = GetNamedBitmap('Black')
|
|
btn = wx.BitmapButton(self, ID_BLACK_BG, bmp, style=wx.BU_EXACTFIT)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
|
|
btn.SetToolTip(_("Set background to black"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
bmp = GetNamedBitmap('Checked')
|
|
btn = wx.BitmapButton(self, ID_CHECK_BG, bmp, style=wx.BU_EXACTFIT)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
|
|
btn.SetToolTip(_("Set background to chekered pattern"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
|
|
hbox_ctrls.AddSpacer(7)
|
|
|
|
bmp = GetNamedBitmap('NoFrame')
|
|
btn = wx.BitmapButton(self, ID_NO_FRAME, bmp, style=wx.BU_EXACTFIT)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
|
|
btn.SetToolTip(_("No framing around image"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
bmp = GetNamedBitmap('BoxFrame')
|
|
btn = wx.BitmapButton(self, ID_BOX_FRAME, bmp, style=wx.BU_EXACTFIT)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
|
|
btn.SetToolTip(_("Frame image with a box"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
bmp = GetNamedBitmap('CropFrame')
|
|
btn = wx.BitmapButton(self, ID_CROP_FRAME, bmp, style=wx.BU_EXACTFIT|wx.BORDER_SIMPLE)
|
|
self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
|
|
btn.SetToolTip(_("Frame image with a dimmed background"))
|
|
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
|
|
|
|
|
|
def SetValue(self, file_nm): # display the selected file in the panel
|
|
self.view.SetValue(file_nm)
|
|
|
|
def SetBackgroundMode(self, mode):
|
|
self.view.SetBackgroundMode(mode)
|
|
|
|
def SetBorderMode(self, mode):
|
|
self.view.SetBorderMode(mode)
|
|
|
|
def OnSetImgBackground(self, event):
|
|
mode = event.GetId()
|
|
self.SetBackgroundMode(mode)
|
|
|
|
def OnSetBorderMode(self, event):
|
|
mode = event.GetId()
|
|
self.SetBorderMode(mode)
|
|
|
|
|
|
|
|
class ImageDialog(wx.Dialog):
|
|
"""
|
|
:class:`ImageDialog` derived from :class:`Dialog` allows the user
|
|
to display images and to select an image.
|
|
"""
|
|
def __init__(self, parent, set_dir = None):
|
|
"""
|
|
Default class constructor.
|
|
|
|
:param Window `parent`: parent window.
|
|
:param string `set_dir`: path to set as working directory
|
|
|
|
"""
|
|
wx.Dialog.__init__(self, parent, -1, _("Image Browser"),
|
|
wx.DefaultPosition, (400, 400),
|
|
style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
|
|
|
|
self.set_dir = os.getcwd()
|
|
self.set_file = None
|
|
|
|
if set_dir != None:
|
|
if os.path.exists(set_dir): # set to working directory if nothing set
|
|
self.set_dir = set_dir
|
|
|
|
vbox_top = wx.BoxSizer(wx.VERTICAL)
|
|
self.SetSizer(vbox_top)
|
|
|
|
hbox_loc = wx.BoxSizer(wx.HORIZONTAL)
|
|
vbox_top.Add(hbox_loc, 0, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 0)
|
|
|
|
loc_label = wx.StaticText( self, -1, "Folder:")
|
|
hbox_loc.Add(loc_label, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ADJUST_MINSIZE, 5)
|
|
|
|
self.dir = wx.TextCtrl( self, -1, self.set_dir, style=wx.TE_RICH|wx.TE_PROCESS_ENTER)
|
|
self.Bind(wx.EVT_TEXT_ENTER, self.OnDirectoryTextSet, self.dir)
|
|
hbox_loc.Add(self.dir, 1, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 5)
|
|
|
|
up_bmp = wx.ArtProvider.GetBitmap(wx.ART_GO_DIR_UP, wx.ART_BUTTON, (16,16))
|
|
btn = wx.BitmapButton(self, -1, up_bmp)
|
|
btn.SetHelpText(_("Up one level"))
|
|
btn.SetToolTip(_("Up one level"))
|
|
self.Bind(wx.EVT_BUTTON, self.OnUpDirectory, btn)
|
|
hbox_loc.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 2)
|
|
|
|
folder_bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_BUTTON, (16,16))
|
|
btn = wx.BitmapButton(self, -1, folder_bmp)
|
|
btn.SetHelpText(_("Browse for a &folder..."))
|
|
btn.SetToolTip(_("Browse for a folder..."))
|
|
self.Bind(wx.EVT_BUTTON, self.OnChooseDirectory, btn)
|
|
hbox_loc.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
|
|
|
|
hbox_nav = wx.BoxSizer(wx.HORIZONTAL)
|
|
vbox_top.Add(hbox_nav, 0, wx.ALIGN_LEFT|wx.ALL, 0)
|
|
|
|
|
|
label = wx.StaticText( self, -1, "Files of type:")
|
|
hbox_nav.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
|
|
|
|
self.fl_ext = '*.bmp' # initial setting for file filtering
|
|
self.GetFiles() # get the file list
|
|
|
|
self.fl_ext_types = (
|
|
# display, filter
|
|
("All supported formats", "All"),
|
|
("BMP (*.bmp)", "*.bmp"),
|
|
("GIF (*.gif)", "*.gif"),
|
|
("PNG (*.png)", "*.png"),
|
|
("JPEG (*.jpg)", "*.jpg"),
|
|
("ICO (*.ico)", "*.ico"),
|
|
("PNM (*.pnm)", "*.pnm"),
|
|
("PCX (*.pcx)", "*.pcx"),
|
|
("TIFF (*.tif)", "*.tif"),
|
|
("All Files", "*.*"),
|
|
)
|
|
self.set_type,self.fl_ext = self.fl_ext_types[0] # initial file filter setting
|
|
self.fl_types = [ x[0] for x in self.fl_ext_types ]
|
|
self.sel_type = wx.ComboBox( self, -1, self.set_type,
|
|
wx.DefaultPosition, wx.DefaultSize, self.fl_types,
|
|
wx.CB_DROPDOWN )
|
|
# after this we don't care about the order any more
|
|
self.fl_ext_types = dict(self.fl_ext_types)
|
|
|
|
self.Bind(wx.EVT_COMBOBOX, self.OnSetType, self.sel_type)
|
|
hbox_nav.Add(self.sel_type, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
|
|
|
|
splitter = wx.SplitterWindow( self, -1, wx.DefaultPosition, wx.Size(100, 100), 0 )
|
|
splitter.SetMinimumPaneSize(100)
|
|
|
|
split_left = wx.Panel( splitter, -1, wx.DefaultPosition, wx.DefaultSize,
|
|
wx.NO_BORDER|wx.TAB_TRAVERSAL )
|
|
vbox_left = wx.BoxSizer(wx.VERTICAL)
|
|
split_left.SetSizer(vbox_left)
|
|
|
|
|
|
self.tb = tb = wx.ListBox( split_left, -1, wx.DefaultPosition, wx.DefaultSize,
|
|
self.fl_list, wx.LB_SINGLE )
|
|
self.Bind(wx.EVT_LISTBOX, self.OnListClick, tb)
|
|
self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnListDClick, tb)
|
|
vbox_left.Add(self.tb, 1, wx.GROW|wx.ALL, 0)
|
|
|
|
width, height = self.tb.GetSize()
|
|
|
|
split_right = wx.Panel( splitter, -1, wx.DefaultPosition, wx.DefaultSize,
|
|
wx.NO_BORDER|wx.TAB_TRAVERSAL )
|
|
vbox_right = wx.BoxSizer(wx.VERTICAL)
|
|
split_right.SetSizer(vbox_right)
|
|
|
|
self.image_view = ImagePanel( split_right )
|
|
vbox_right.Add(self.image_view, 1, wx.GROW|wx.ALL, 0)
|
|
|
|
splitter.SplitVertically(split_left, split_right, 150)
|
|
vbox_top.Add(splitter, 1, wx.GROW|wx.ALL, 5)
|
|
|
|
hbox_btns = wx.BoxSizer(wx.HORIZONTAL)
|
|
vbox_top.Add(hbox_btns, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
|
|
|
|
ok_btn = wx.Button( self, wx.ID_OPEN, "", wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
self.Bind(wx.EVT_BUTTON, self.OnOk, ok_btn)
|
|
#ok_btn.SetDefault()
|
|
hbox_btns.Add(ok_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
|
|
|
|
cancel_btn = wx.Button( self, wx.ID_CANCEL, "",
|
|
wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
hbox_btns.Add(cancel_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
|
|
|
|
self.ResetFiles()
|
|
|
|
def ChangeFileTypes(self, ft_tuple):
|
|
"""
|
|
Change list of file types to be supported
|
|
|
|
:param tuple `ft_tuple`: tuple of files types, e.g. to support just
|
|
.gif and .png you would use:
|
|
|
|
(("GIF (*.gif)", "*.gif"),
|
|
("PNG (*.png)", "*.png"))
|
|
|
|
"""
|
|
|
|
self.fl_ext_types = ft_tuple
|
|
self.set_type, self.fl_ext = self.fl_ext_types[0] # initial file filter setting
|
|
self.fl_types = [ x[0] for x in self.fl_ext_types ]
|
|
self.sel_type.Clear()
|
|
self.sel_type.AppendItems(self.fl_types)
|
|
self.sel_type.SetSelection(0)
|
|
self.fl_ext_types = dict(self.fl_ext_types)
|
|
|
|
def GetFiles(self):
|
|
# get the file list using directory and extension values
|
|
if self.fl_ext == "All":
|
|
all_files = []
|
|
|
|
if self.fl_types[-1] == 'All Files':
|
|
allTypes = self.fl_types[-1:]
|
|
else:
|
|
allTypes = self.fl_types[1:]
|
|
for ftypes in allTypes: # get list of all
|
|
filter = self.fl_ext_types[ftypes]
|
|
#print("filter = ", filter)
|
|
self.fl_val = FindFiles(self, self.set_dir, filter)
|
|
all_files = all_files + self.fl_val.files # add to list of files
|
|
|
|
self.fl_list = all_files
|
|
else:
|
|
self.fl_val = FindFiles(self, self.set_dir, self.fl_ext)
|
|
self.fl_list = self.fl_val.files
|
|
|
|
|
|
self.fl_list.sort() # sort the file list
|
|
# prepend the directories
|
|
self.fl_ndirs = len(self.fl_val.dirs)
|
|
self.fl_list = sorted(self.fl_val.dirs) + self.fl_list
|
|
|
|
def DisplayDir(self):
|
|
# display the working directory
|
|
if self.dir:
|
|
ipt = self.dir.GetInsertionPoint()
|
|
self.dir.SetValue(self.set_dir)
|
|
self.dir.SetInsertionPoint(ipt)
|
|
|
|
def OnSetType(self, event):
|
|
val = event.GetString() # get file type value
|
|
self.fl_ext = self.fl_ext_types[val]
|
|
self.ResetFiles()
|
|
|
|
def OnListDClick(self, event):
|
|
self.OnOk('dclick')
|
|
|
|
def OnListClick(self, event):
|
|
val = event.GetSelection()
|
|
self.SetListValue(val)
|
|
|
|
def SetListValue(self, val):
|
|
file_nm = self.fl_list[val]
|
|
self.set_file = file_val = os.path.join(self.set_dir, file_nm)
|
|
if val>=self.fl_ndirs:
|
|
self.image_view.SetValue(file_val)
|
|
else:
|
|
self.image_view.SetValue(None)
|
|
|
|
def OnDirectoryTextSet(self,event):
|
|
event.Skip()
|
|
path = event.GetString()
|
|
if os.path.isdir(path):
|
|
self.set_dir = path
|
|
self.ResetFiles()
|
|
return
|
|
|
|
if os.path.isfile(path):
|
|
dname,fname = os.path.split(path)
|
|
if os.path.isdir(dname):
|
|
self.ResetFiles()
|
|
# try to select fname in list
|
|
try:
|
|
idx = self.fl_list.index(fname)
|
|
self.tb.SetSelection(idx)
|
|
self.SetListValue(idx)
|
|
return
|
|
except ValueError:
|
|
pass
|
|
|
|
wx.Bell()
|
|
|
|
def OnUpDirectory(self, event):
|
|
sdir = os.path.split(self.set_dir)[0]
|
|
self.set_dir = sdir
|
|
self.ResetFiles()
|
|
|
|
def OnChooseDirectory(self, event):
|
|
# set the new directory
|
|
dlg = wx.DirDialog(self)
|
|
dlg.SetPath(self.set_dir)
|
|
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
self.set_dir = dlg.GetPath()
|
|
self.ResetFiles()
|
|
|
|
dlg.Destroy()
|
|
|
|
def ResetFiles(self):
|
|
# refresh the display with files and initial image
|
|
self.DisplayDir()
|
|
self.GetFiles()
|
|
|
|
# Changed 12/8/03 jmg
|
|
#
|
|
# o Clear listbox first
|
|
# o THEN check to see if there are any valid files of the selected
|
|
# type,
|
|
# o THEN if we have any files to display, set the listbox up,
|
|
#
|
|
# OTHERWISE
|
|
#
|
|
# o Leave it cleared
|
|
# o Clear the image viewer.
|
|
#
|
|
# This avoids a nasty assert error.
|
|
#
|
|
self.tb.Clear()
|
|
|
|
if len(self.fl_list):
|
|
self.tb.Set(self.fl_list)
|
|
|
|
for idir in range(self.fl_ndirs):
|
|
d = self.fl_list[idir]
|
|
# mark directories as 'True' with client data
|
|
self.tb.SetClientData(idir, True)
|
|
self.tb.SetString(idir,'['+d+']')
|
|
|
|
try:
|
|
self.tb.SetSelection(0)
|
|
self.SetListValue(0)
|
|
except Exception:
|
|
self.image_view.SetValue(None)
|
|
else:
|
|
self.image_view.SetValue(None)
|
|
|
|
def GetFile(self):
|
|
"""
|
|
Get selected file
|
|
|
|
:return: File selected or None
|
|
"""
|
|
return self.set_file
|
|
|
|
def GetDirectory(self):
|
|
"""
|
|
Get directory
|
|
|
|
:return: get the current directory
|
|
|
|
"""
|
|
return self.set_dir
|
|
|
|
def OnCancel(self, event):
|
|
self.result = None
|
|
self.EndModal(wx.ID_CANCEL)
|
|
|
|
def OnOk(self, event):
|
|
if os.path.isdir(self.set_file):
|
|
sdir = os.path.split(self.set_file)
|
|
|
|
#os.path.normapth?
|
|
if sdir and sdir[-1]=='..':
|
|
sdir = os.path.split(sdir[0])[0]
|
|
sdir = os.path.split(sdir)
|
|
self.set_dir = os.path.join(*sdir)
|
|
self.set_file = None
|
|
self.ResetFiles()
|
|
elif event != 'dclick':
|
|
self.result = self.set_file
|
|
self.EndModal(wx.ID_OK)
|
|
|
|
|
|
|
|
class FindFiles:
|
|
def __init__(self, parent, dir, mask, with_dirs=True):
|
|
filelist = []
|
|
dirlist = [".."]
|
|
self.dir = dir
|
|
self.file = ""
|
|
mask = mask.upper()
|
|
pattern = self.MakeRegex(mask)
|
|
|
|
for i in os.listdir(dir):
|
|
if i == "." or i == "..":
|
|
continue
|
|
|
|
path = os.path.join(dir, i)
|
|
|
|
if os.path.isdir(path):
|
|
dirlist.append(i)
|
|
continue
|
|
|
|
path = path.upper()
|
|
value = i.upper()
|
|
|
|
if pattern.match(value) != None:
|
|
filelist.append(i)
|
|
|
|
|
|
self.files = filelist
|
|
if with_dirs:
|
|
self.dirs = dirlist
|
|
|
|
def MakeRegex(self, pattern):
|
|
import re
|
|
f = "" # Set up a regex for file names
|
|
|
|
for ch in pattern:
|
|
if ch == "*":
|
|
f = f + ".*"
|
|
elif ch == ".":
|
|
f = f + "\."
|
|
elif ch == "?":
|
|
f = f + "."
|
|
else:
|
|
f = f + ch
|
|
|
|
return re.compile(f+'$')
|
|
|
|
def StripExt(self, file_nm):
|
|
fl_fld = os.path.splitext(file_nm)
|
|
fl_name = fl_fld[0]
|
|
ext = fl_fld[1]
|
|
return ext[1:]
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
# This part of the file was generated by C:\Python25\Scripts\img2py
|
|
# then edited slightly.
|
|
|
|
from wx.lib.embeddedimage import PyEmbeddedImage
|
|
|
|
IMG_CATALOG = {}
|
|
|
|
IMG_CATALOG['White'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAIUlE"
|
|
"QVQYlWNgIAIwMjAw/P//H58KRkYmYkwaVUScIqIAAMjRAxRV8+5MAAAAAElFTkSuQmCC")
|
|
|
|
IMG_CATALOG['Grey'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAIklE"
|
|
"QVQYlWNgIAIwMjAwnDlzBo8KExMTJmJMGlVEnCKiAAC24wMULFLZGAAAAABJRU5ErkJggg==")
|
|
|
|
IMG_CATALOG['Black'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAADklE"
|
|
"QVQYlWNgGAVDFQAAAbwAATN8mzYAAAAASUVORK5CYII=")
|
|
|
|
IMG_CATALOG['Checked'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAMUlE"
|
|
"QVQYlWNgIAIwMjAwnDlzBlnI2NgYRQUjIxMxJtFZEQsDhkvPnj07sG4iShFRAAAougYW+urT"
|
|
"ZwAAAABJRU5ErkJggg==")
|
|
|
|
IMG_CATALOG['NoFrame'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAANklE"
|
|
"QVQYla2PQQoAIBACnej/X7ZbUEQtkudhVKkQJNm+EdAqpggCgB+m44kFml1bY39q0k15Bsuc"
|
|
"CR/z8ajiAAAAAElFTkSuQmCC")
|
|
|
|
IMG_CATALOG['BoxFrame'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAQ0lE"
|
|
"QVQYlZ2O0QoAIAgDd9L//7I9CFEhJu1psmNOaghJ7l4RYJ0m1U0R2X4vevcHVOiG0tcHBABh"
|
|
"8nWpIhpPLtn0rwm4WyD966x3sgAAAABJRU5ErkJggg==")
|
|
|
|
IMG_CATALOG['CropFrame'] = PyEmbeddedImage(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAASUlE"
|
|
"QVQYlb2QMQrAQAgEZ0P+q0/RF5tCuIMUh2myhcgyjCAMIiAiDoS7XxPTCLrXZmaAJKCqgMz8"
|
|
"YHpD7ThBkvpcz93z6wtGeQD/sQ8bfXs8NAAAAABJRU5ErkJggg==")
|
|
|