Class: TkImageMap::ImageMap

Inherits:
TkCanvas show all
Defined in:
lib/drx/tk/imagemap.rb

Overview

A widget to show an image together with an HTML imagemap.

Instance Method Summary collapse

Methods inherited from TkCanvas

#coords, #raise

Constructor Details

#initialize(parent, *rest) ⇒ ImageMap

Returns a new instance of ImageMap.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/drx/tk/imagemap.rb', line 41

def initialize(parent, *rest)
  super
  @hover_region = nil
  @active_region = nil
  @hotspots = []
  @image_widget = nil
  @select_command = proc {}
  @double_select_command = proc {}

  # Attach scrolling to middle button.
  canvas.bind('2', proc { |x,y| canvas.scan_mark(x,y) }, '%x %y')
  canvas.bind('B2-Motion', proc { |x,y| canvas.scan_dragto x, y }, '%x %y')

  canvas.pack :expand => true, :fill => 'both'

  ['Motion','Control-Motion'].each { |sequence|
    canvas.bind sequence do |evt|
      x, y = canvas.coords(evt)
      spot = canvas.find('overlapping', x, y, x + 1, y + 1).first
      if spot and spot.cget('tags').include? 'hotspot'
        new_hover_region = spot.hotspot_region
      else
        new_hover_region = nil
      end
      if new_hover_region != @hover_region
        @hover_region[:hover_spot].configure(:state => 'hidden') if @hover_region
        @hover_region = new_hover_region
        @hover_region[:hover_spot].configure(:state => 'disabled') if @hover_region # like 'visible'
        if sequence['Control']
          self.active_region = @hover_region
        end
      end
    end
  }
  canvas.bind 'Button-1' do |evt|
    x, y = canvas.coords(evt)
    spot = canvas.find('overlapping', x, y, x+1, y+1).first
    if spot and spot.cget('tags').include? 'hotspot'
      self.active_region = spot.hotspot_region
    else
      self.active_region = nil
    end
  end
  canvas.bind 'Double-Button-1' do
    @double_select_command.call(active_url) if @active_region
  end
  # Middle button: vertical scrolling.
  canvas.bind 'Button-4' do
    canvas.yview_scroll(-1, 'units')
  end
  canvas.bind 'Button-5' do
    canvas.yview_scroll(1, 'units')
  end
  # Middle button: horizontal scrolling.
  canvas.bind 'Shift-Button-4' do
    canvas.xview_scroll(-1, 'units')
  end
  canvas.bind 'Shift-Button-5' do
    canvas.xview_scroll(1, 'units')
  end
end

Instance Method Details

#active_region=(region) ⇒ Object



103
104
105
106
107
108
109
110
# File 'lib/drx/tk/imagemap.rb', line 103

def active_region=(region)
  if region != @active_region
    @active_region[:active_spot].configure(:state => 'hidden') if @active_region
    @active_region = region
    @active_region[:active_spot].configure(:state => 'disabled') if @active_region # like 'visible'
    @select_command.call(active_url)
  end
end

#active_urlObject



112
113
114
# File 'lib/drx/tk/imagemap.rb', line 112

def active_url
  @active_region ? @active_region[:url] : nil
end

#active_url=(newurl) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/drx/tk/imagemap.rb', line 116

def active_url=(newurl)
  catch :found do
    @hotspots.each { |region|
      if region[:url] == newurl
        self.active_region = region
        throw :found
      end
    }
    # It was not found:
    self.active_region = nil
  end
end

#canvasObject

I’m not yet sure I want ImageMap to be a TkCanvas directly (an alternative would be for it to control an external canvas). So, for future compatibility, I access the canvas through canvas() instead of assuming it’s ‘self’.



37
38
39
# File 'lib/drx/tk/imagemap.rb', line 37

def canvas
  self
end

#double_select_command(&block) ⇒ Object



24
25
26
# File 'lib/drx/tk/imagemap.rb', line 24

def double_select_command &block
  @double_select_command = block
end

#image=(pathname) ⇒ Object



129
130
131
132
# File 'lib/drx/tk/imagemap.rb', line 129

def image=(pathname)
  @image = TkPhotoImage.new :file => pathname
  canvas.configure :scrollregion => [0, 0, @image.width, @image.height]
end

#image_map=(pathname) ⇒ Object

You must call this after image=()



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/drx/tk/imagemap.rb', line 135

def image_map=(pathname)
  # Delete the previous spot widgets and the image widget.
  canvas.find('all').each {|w| w.destroy }
  canvas.xview_moveto(0)
  canvas.yview_moveto(0)

  @hotspots = Utils.parse_imap(pathname)

  #
  # Create the back spots.
  #
  @hotspots.each do |region|
    args = [canvas, *(region[:args])]
    opts = {
      :fill => 'red',
      :tags => ['hotspot']
    }
    back_spot = region[:class].new *(args + [opts])
    # The following won't work, so we have to use define_method instead.
    #def back_spot.hotspot_region
    #   region
    #end
    meta = class << back_spot; self; end
    meta.send :define_method, :hotspot_region do
      region
    end
  end

  @image_widget = TkcImage.new(canvas,0,0, :image => @image, :anchor=> 'nw')

  #
  # Create the hover spots.
  #
  @hotspots.each do |region|
    args = [canvas, *(region[:args])]
    opts = {
      :dash => '. ',
      :width => 5,
      :fill => nil,
      :outline => 'black',
      :state => 'hidden'
    }
    region[:hover_spot] = region[:class].new *(args + [opts])
    opts = {
      :width => 5,
      :fill => nil,
      :outline => 'black',
      :state => 'hidden'
    }
    region[:active_spot] = region[:class].new *(args + [opts])
  end
end

#select_command(&block) ⇒ Object



20
21
22
# File 'lib/drx/tk/imagemap.rb', line 20

def select_command &block
  @select_command = block
end

#urlsObject

Returns all the URLs.



29
30
31
# File 'lib/drx/tk/imagemap.rb', line 29

def urls
  @hotspots.map { |h| h[:url] }
end