diff --git a/wxPython/wx/lib/imagebrowser.py b/wxPython/wx/lib/imagebrowser.py index 72b1346d53..a9297794f6 100644 --- a/wxPython/wx/lib/imagebrowser.py +++ b/wxPython/wx/lib/imagebrowser.py @@ -2,18 +2,28 @@ # Name: BrowseImage.py # Purpose: Display and Select Image Files # -# Author: Lorne White +# Original Author: Lorne White # -# Version: 1.0 -# Date: January 29, 2002 +# Version: 2.0 +# Date: June 16, 2007 # Licence: wxWindows license #---------------------------------------------------------------------------- -# 1.0 Release -# 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 -# +# 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) @@ -22,18 +32,32 @@ # 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 +# #--------------------------------------------------------------------------- import os import sys - import wx -dir_path = os.getcwd() - #--------------------------------------------------------------------------- +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): if file_nm is None: return None @@ -42,92 +66,326 @@ def ConvertBMP(file_nm): ext = fl_fld[1] ext = ext[1:].lower() - image = wx.Image(file_nm, wx.BITMAP_TYPE_ANY) - return image + # 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 GetSize(file_nm): # for scaling image values - image = ConvertBMP(file_nm) - bmp = image.ConvertToBitmap() - size = bmp.GetWidth(), bmp.GetHeight() - return size +def GetCheckeredBitmap(blocksize=8,ntiles=4,rgb0='\xFF', rgb1='\xCC'): + """Creates a square RGB checkered bitmap using the two specified colors. + + Inputs: + - blocksize: the number of pixels in each solid color square + - ntiles: the number of tiles along width and height. Each tile is 2x2 blocks. + - rbg0,rgb1: the first and second colors, as 3-byte strings. + If only 1 byte is provided, it is treated as a grey value. + + The bitmap returned will have width = height = blocksize*ntiles*2 + """ + 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.BitmapFromBuffer(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): - wx.Window.__init__(self, parent, id, pos, size) - self.win = parent + 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.back_color = 'WHITE' - self.border_color = 'BLACK' + + 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.image_sizex = size[0] - self.image_sizey = size[1] - self.image_posx = pos[0] - self.image_posy = pos[1] self.Bind(wx.EVT_PAINT, self.OnPaint) - - def OnPaint(self, event): - dc = wx.PaintDC(self) - self.DrawImage(dc) + 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 DrawBorder(self, dc): - brush = wx.Brush(wx.NamedColour(self.back_color), wx.SOLID) - dc.SetBrush(brush) - dc.SetPen(wx.Pen(wx.NamedColour(self.border_color), 1)) - dc.DrawRectangle(0, 0, self.image_sizex, self.image_sizey) + 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 not dc: + dc = wx.ClientDC(self) + rect = self.GetUpdateRegion().GetBox() + dc.SetClippingRect(rect) + 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): - try: - image = self.image - except: + + if not hasattr(self,'image') or self.image is None: return - self.DrawBorder(dc) + 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() - if image is None: - return + # squeeze iwidth x iheight image into window, preserving aspect ratio - try: - bmp = image.ConvertToBitmap() - except: - return + xfactor = float(wwidth) / iwidth + yfactor = float(wheight) / iheight - iwidth = bmp.GetWidth() # dimensions of image file - iheight = bmp.GetHeight() + if xfactor < 1.0 and xfactor < yfactor: + scale = xfactor + elif yfactor < 1.0 and yfactor < xfactor: + scale = yfactor + else: + scale = 1.0 - diffx = (self.image_sizex - iwidth)/2 # center calc - if iwidth >= self.image_sizex -10: # if image width fits in window adjust - diffx = 5 - iwidth = self.image_sizex - 10 + owidth = int(scale*iwidth) + oheight = int(scale*iheight) - diffy = (self.image_sizey - iheight)/2 # center calc - if iheight >= self.image_sizey - 10: # if image height fits in window adjust - diffy = 5 - iheight = self.image_sizey - 10 + 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.SetToolTipString("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.SetToolTipString("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.SetToolTipString("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.SetToolTipString("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.SetToolTipString("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.SetToolTipString("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.SetToolTipString("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) - image.Rescale(iwidth, iheight) # rescale to fit the window - image.ConvertToBitmap() - bmp = image.ConvertToBitmap() - dc.DrawBitmap(bmp, diffx, diffy) # draw the image to window class ImageDialog(wx.Dialog): def __init__(self, parent, set_dir = None): - wx.Dialog.__init__(self, parent, -1, "Image Browser", wx.DefaultPosition, (400, 400)) - - self.x_pos = 30 # initial display positions - self.y_pos = 20 - self.delta = 20 - - size = wx.Size(80, -1) + 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 @@ -136,77 +394,110 @@ class ImageDialog(wx.Dialog): if os.path.exists(set_dir): # set to working directory if nothing set self.set_dir = set_dir - self.dir_x = self.x_pos - self.dir_y = self.y_pos - self.dir = wx.StaticText(self, -1, self.set_dir, (self.dir_x, self.dir_y), (250, -1)) + vbox_top = wx.BoxSizer(wx.VERTICAL) + self.SetSizer(vbox_top) - self.y_pos = self.y_pos + self.delta + hbox_loc = wx.BoxSizer(wx.HORIZONTAL) + vbox_top.Add(hbox_loc, 0, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 0) - btn = wx.Button(self, 12331, ' Set Directory ', (self.x_pos, self.y_pos)) - self.Bind(wx.EVT_BUTTON, self.SetDirect, btn) + 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.type_posy = self.y_pos # save the y position for the image type combo + 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.SetToolTipString("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.SetToolTipString("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.y_pos = self.y_pos + self.delta + 10 - self.list_height = 150 + 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) - # List of Labels - self.tb = tb = wx.ListBox(self, -1, (self.x_pos, self.y_pos), - (160, self.list_height), self.fl_list, - wx.LB_SINGLE ) + 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() - image_posx = self.x_pos + width + 20 # positions for setting the image window - image_posy = self.y_pos - image_sizex = 150 - image_sizey = self.list_height - self.fl_types = [ - "All Images", "Bmp", "Gif", "Png", "Jpg", "Ico", "Pnm", - "Pcx", "Tif", "All Files" - ] + 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.fl_ext_types = { - "All Images": "All", - "Bmp": "*.bmp", - "Gif": "*.gif", - "Png": "*.png", - "Jpg": "*.jpg", - "Ico": "*.ico", - "Pnm": "*.pnm", - "Pcx": "*.pcx", - "Tif": "*.tif", - "All Files": "*.*" - } + self.image_view = ImagePanel( split_right ) + vbox_right.Add(self.image_view, 1, wx.GROW|wx.ALL, 0) - self.set_type = self.fl_types[0] # initial file filter setting - self.fl_ext = self.fl_ext_types[self.set_type] + splitter.SplitVertically(split_left, split_right, 150) + vbox_top.Add(splitter, 1, wx.GROW|wx.ALL, 5) - self.sel_type = wx.ComboBox(self, -1, self.set_type, (image_posx , self.type_posy), - (150, -1), self.fl_types, wx.CB_DROPDOWN) - self.Bind(wx.EVT_COMBOBOX, self.OnSetType, self.sel_type) + hbox_btns = wx.BoxSizer(wx.HORIZONTAL) + vbox_top.Add(hbox_btns, 0, wx.ALIGN_RIGHT|wx.ALL, 5) - self.image_view = ImageView( self, pos=(image_posx, image_posy), - size=(image_sizex, image_sizey)) + 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) - self.y_pos = self.y_pos + height + 20 - - btn = wx.Button(self, -1, ' Select ', (100, self.y_pos), size) - self.Bind(wx.EVT_BUTTON, self.OnOk, btn) - - wx.Button(self, wx.ID_CANCEL, 'Cancel', (250, self.y_pos), size) - - self.y_pos = self.y_pos + self.delta - fsize = (400, self.y_pos + 50) # resize dialog for final vertical position - self.SetSize(fsize) + 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 GetFiles(self): # get the file list using directory and extension values if self.fl_ext == "All": all_files = [] @@ -222,11 +513,17 @@ class ImageDialog(wx.Dialog): 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: - self.dir.SetLabel(self.set_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 @@ -234,7 +531,7 @@ class ImageDialog(wx.Dialog): self.ResetFiles() def OnListDClick(self, event): - self.OnOk(0) + self.OnOk('dclick') def OnListClick(self, event): val = event.GetSelection() @@ -243,9 +540,40 @@ class ImageDialog(wx.Dialog): def SetListValue(self, val): file_nm = self.fl_list[val] self.set_file = file_val = os.path.join(self.set_dir, file_nm) - self.image_view.SetValue(file_val) + if val>=self.fl_ndirs: + self.image_view.SetValue(file_val) + else: + self.image_view.SetValue(None) - def SetDirect(self, event): # set the new directory + 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) @@ -278,6 +606,12 @@ class ImageDialog(wx.Dialog): if len(self.fl_list): self.tb.Set(self.fl_list) + for idir in xrange(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) @@ -297,24 +631,24 @@ class ImageDialog(wx.Dialog): self.EndModal(wx.ID_CANCEL) def OnOk(self, event): - self.result = self.set_file - self.EndModal(wx.ID_OK) + 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) -def OnFileDlg(self): - dlg = wx.FileDialog(self, "Choose an Image File", ".", "", - "Bmp (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg", wx.OPEN) - - if dlg.ShowModal() == wx.ID_OK: - path = dlg.GetPath() - else: - path = None - - dlg.Destroy() - return path class FindFiles: - def __init__(self, parent, dir, mask): + def __init__(self, parent, dir, mask, with_dirs=True): filelist = [] dirlist = [".."] self.dir = dir @@ -327,13 +661,21 @@ class FindFiles: 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 @@ -356,3 +698,166 @@ class FindFiles: 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. + +import cStringIO, zlib + + +IMG_CATALOG = {} + +class ImageClass: pass + +def getWhiteData(): + return zlib.decompress( +'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\ +o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d