#!/usr/bin/env ruby # frozen_string_literal: false # # viewIcons.rb # # -- Display icons from icon library. # # -- Copy the clicked icon data (command string of creating # a TkPhotoImage instance) to the clipboard. # require 'tk' require 'tkextlib/ICONS' class ViewIcons ##################################### private ##################################### def _create_controls @controls = base = TkFrame.new columns = TkFrame.new(base) line1 = TkFrame.new(base, :height=>2, :borderwidth=>1, :relief=>:sunken) line2 = TkFrame.new(base, :height=>2, :borderwidth=>1, :relief=>:sunken) lbl_library = TkLabel.new(base, :font=>@boldfont, :text=>'Library') lbl_groups = TkLabel.new(base, :font=>@boldfont, :text=>'Groups') lbl_columns = TkLabel.new(base, :font=>@boldfont, :text=>'Columns') ent_library = TkEntry.new(base, :width=>50, :textvariable=>@library) ent_groups = TkEntry.new(base, :width=>50, :textvariable=>@groups) btn_browse = TkButton.new(base, :text=>'Browse', :command=>method(:select_icons)) btn_view = TkButton.new(base, :text=>'View', :command=>method(:display_icons)) btn_exit = TkButton.new(base, :text=>'Exit', :command=>proc{exit}) @column_btns = {} 6.step(20, 2){|i| @column_btns[i] = TkButton.new(columns, :text=>i.to_s, :width=>2, :command=>proc{set_columns(i)} ).pack(:side=>:left) } @column_btns[@columns][:relief] = :sunken lbl_library.grid(:row=>0, :column=>0, :padx=>4) ent_library.grid(:row=>0, :column=>1) btn_browse.grid(:row=>0, :column=>2, :padx=>4, :pady=>2, :sticky=>:ew) line1.grid(:row=>1, :column=>0, :pady=>2, :columnspan=>3, :sticky=>:ew) lbl_groups.grid(:row=>2, :column=>0, :padx=>4) ent_groups.grid(:row=>2, :column=>1) btn_view.grid(:row=>2, :column=>2, :padx=>4, :pady=>2, :sticky=>:ew) line1.grid(:row=>3, :column=>0, :pady=>2, :columnspan=>3, :sticky=>:ew) lbl_columns.grid(:row=>4, :column=>0, :padx=>4) columns.grid(:row=>4, :column=>1, :padx=>2, :sticky=>:ew) btn_exit.grid(:row=>4, :column=>2, :padx=>4, :pady=>2, :sticky=>:ew) base.pack ent_library.bind('Return', method(:display_icons), '') ent_groups.bind('Return', method(:display_icons), '') end def _create_display base = TkFrame.new(:borderwidth=>2, :relief=>:sunken) @icons_window = icons = TkCanvas.new(base) xscr = icons.xscrollbar(TkScrollbar.new(base)) yscr = icons.yscrollbar(TkScrollbar.new(base)) icons.grid(:row=>0, :column=>0, :sticky=>:news) yscr.grid(:row=>0, :column=>1, :sticky=>:ns) xscr.grid(:row=>1, :column=>0, :sticky=>:ew) base.grid_columnconfigure(0, :weight=>1) base.grid_columnconfigure(1, :weight=>0) base.grid_rowconfigure(0, :weight=>1) base.grid_rowconfigure(1, :weight=>0) # yscr.pack(:side=>:right, :fill=>:y) # xscr.pack(:side=>:bottom, :fill=>:x) # icons.pack(:side=>:left, :fill=>:both, :expand=>true) @icons_layout = TkFrame.new(icons).pack TkcWindow.create(icons, 0, 0, :anchor=>:nw, :window=>@icons_layout) @icons_layout.bind('Configure', method(:layout_resize), '') base.pack(:expand=>true, :fill=>:both) end def _create_info_window @info_window = TkToplevel.new(:background=>'lightyellow', :borderwidth=>1, :relief=>:solid){|w| lbl_name = TkLabel.new(w, :text=>'Name', :background=>'lightyellow', :font=>@boldfont, :justify=>:left) lbl_grps = TkLabel.new(w, :text=>'Groups', :background=>'lightyellow', :font=>@boldfont, :justify=>:left) lbl_type = TkLabel.new(w, :text=>'Type', :background=>'lightyellow', :font=>@boldfont, :justify=>:left) lbl_size = TkLabel.new(w, :text=>'Size', :background=>'lightyellow', :font=>@boldfont, :justify=>:left) lbl_name.grid(:row=>0, :column=>0, :sticky=>:w) lbl_grps.grid(:row=>1, :column=>0, :sticky=>:w) lbl_type.grid(:row=>2, :column=>0, :sticky=>:w) lbl_size.grid(:row=>3, :column=>0, :sticky=>:w) @name = TkLabel.new(w, :background=>'lightyellow', :justify=>:left) @grps = TkLabel.new(w, :background=>'lightyellow', :justify=>:left) @type = TkLabel.new(w, :background=>'lightyellow', :justify=>:left) @size = TkLabel.new(w, :background=>'lightyellow', :justify=>:left) @name.grid(:row=>0, :column=>1, :sticky=>:w) @grps.grid(:row=>1, :column=>1, :sticky=>:w) @type.grid(:row=>2, :column=>1, :sticky=>:w) @size.grid(:row=>3, :column=>1, :sticky=>:w) def name(txt) @name['text'] = txt end def groups(txt) @grps['text'] = txt end def type(txt) @type['text'] = txt end def size(txt) @size['text'] = txt end overrideredirect(true) withdraw } end def initialize(init_path = Tk::LIBRARY) init_path = Tk::LIBRARY unless init_path init_path = File.expand_path(init_path) if File.directory?(init_path) @initial_dir = init_path @initial_file = 'tkIcons' else @initial_dir = File.dirname(init_path) @initial_file = File.basename(init_path) end if Tk::PLATFORM['platform'] == 'unix' TkOption.add('*HighlightThickness', 0) end @columns = 14 @command = "" @delay_timer = nil dummy = TkLabel.new @font = dummy.font @boldfont = TkFont.new(@font, :weight=>:bold) @icons = {} @icon_name = {} @icon_info = {} @library = TkVariable.new(File.join(@initial_dir, @initial_file)) @groups = TkVariable.new('*') _create_controls _create_display _create_info_window Tk.root.title('viewIcons') layout_resize Tk.root.resizable(false, true) display_icons end def init_info(item, name) @icon_name[item] = name item.bind('Button-1', method(:clip_info), '%W') item.bind('Enter', method(:delay_info), '%W') item.bind('Leave', method(:cancel_info), '') end def delay_info(item) cancel_info @delay_timer = TkTimer.new(200, 1, proc{ show_info(item) }).start end def cancel_info if @delay_timer @delay_timer.cancel @delay_timer = nil end @info_window.withdraw end def show_info(item) name, groups, type, size = @icon_info[@icon_name[item]] @info_window.name(name) @info_window.groups(groups) @info_window.type(type) @info_window.size(size) info_x = item.winfo_rootx + 10 info_y = item.winfo_rooty + item.winfo_height @info_window.geometry("+#{info_x}+#{info_y}") @info_window.deiconify @info_window.raise @delay_timer = nil end def primary_transfer(offset, max_chars) @command end def lost_selection @command = "" end def clip_info(item) name = @icon_name[item] data_width = 60 cmd = "#{name} = TkPhotoImage.new(:data=><<'EOD')\n" icon_data = Tk::ICONS.query(name, :file=>@library.value, :items=>'d')[0][0] icon_data.scan(/.{1,#{data_width}}/m){|s| cmd << ' ' << s << "\n"} cmd << "EOD\n" @command = cmd TkClipboard.clear TkClipboard.append(@command) if Tk::PLATFORM['platform'] == 'unix' TkSelection.handle(Tk.root, method(:primary_transfer), :selection=>'PRIMARY') TkSelection.set_owner(Tk.root, :selection=>'PRIMARY', :command=>method(:lost_selection)) end Tk.bell end def layout_resize Tk.update bbox = @icons_window.bbox('all') width = @controls.winfo_width - @icons_window.yscrollbar.winfo_width - 8 @icons_window.configure(:width=>width, :scrollregion=>bbox, :xscrollincrement=>'0.1i', :yscrollincrement=>'0.1i') end def select_icons new_lib = Tk.getOpenFile(:initialdir=>@initial_dir, :initialfile=>'tkIcons', :title=>'Select Icon Library', :filetypes=>[ ['Icon Libraries', ['tkIcons*']], ['All Files', ['*']] ]) @library.value = new_lib if new_lib.length != 0 display_icons end def display_icons column = 0 limit = @columns - 1 row = 0 unless File.exist?(@library.value) Tk.messageBox(:icon=>'warning', :message=>'File does not exist', :title=>'viewIcons') return end cursor = Tk.root[:cursor] Tk.root[:cursor] = 'watch' Tk::ICONS.delete(@icons) @icons_frame.destroy if @icons_frame @icons_frame = TkFrame.new(@icons_layout).pack @icons = Tk::ICONS.create(:file=>@library.value, :group=>@groups.value) Tk::ICONS.query(:file=>@library.value, :group=>@groups.value).each{|inf| name = inf[0] @icon_info[name] = inf lbl = TkLabel.new(@icons_frame, :image=>"::icon::#{name}") lbl.grid(:column=>column, :row=>row, :padx=>3, :pady=>3) # lbl.grid_columnconfigure column init_info(lbl, name) if column == limit column = 0 row += 1 else column += 1 end } Tk.root[:cursor] = cursor end def set_columns(columns) @columns = columns 6.step(20, 2){|i| @column_btns[i][:relief] = :raised } @column_btns[@columns][:relief] = :sunken display_icons end end ViewIcons.new(ARGV[0]) Tk.mainloop