Class: CryptopunksGui

Inherits:
Object
  • Object
show all
Includes:
Glimmer
Defined in:
app/cryptopunks_gui.rb

Constant Summary collapse

PALETTES =
['Standard'] + (Palette8bit.constants).map(&:name).map {|palette| palette.split('_').map(&:capitalize).join(' ')}.reject { |palette| palette.include?(' ') }.sort
STYLES =
['Normal', 'Led', 'Sketch']
COLLECTIONS_YAML_URL =
'https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/cryptopunks-collections.yml'
COLLECTIONS_YAML_PATH =
File.expand_path('../cryptopunks-collections.yml', __dir__)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCryptopunksGui

Returns a new instance of CryptopunksGui.



21
22
23
24
25
26
27
28
29
30
31
# File 'app/cryptopunks_gui.rb', line 21

def initialize
  initialize_punk_directory
  initialize_collections_map
  initialize_collection
  load_config
  initialize_defaults
  observe_image_attribute_changes
  create_gui
  self.image_index = 0
  @root.open
end

Instance Attribute Details

#collectionObject

Returns the value of attribute collection.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def collection
  @collection
end

#flipObject

Returns the value of attribute flip.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def flip
  @flip
end

#image_indexObject

Returns the value of attribute image_index.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def image_index
  @image_index
end

#led_round_cornerObject

Returns the value of attribute led_round_corner.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def led_round_corner
  @led_round_corner
end

#led_spacingObject

Returns the value of attribute led_spacing.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def led_spacing
  @led_spacing
end

#mirrorObject

Returns the value of attribute mirror.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def mirror
  @mirror
end

#paletteObject

Returns the value of attribute palette.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def palette
  @palette
end

#sketch_lineObject

Returns the value of attribute sketch_line.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def sketch_line
  @sketch_line
end

#styleObject

Returns the value of attribute style.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def style
  @style
end

#zoomObject

Returns the value of attribute zoom.



19
20
21
# File 'app/cryptopunks_gui.rb', line 19

def zoom
  @zoom
end

Instance Method Details

#add_style_optionsObject



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'app/cryptopunks_gui.rb', line 268

def add_style_options
  @style_options_frame.content {
    @style_options_frame.children.each(&:destroy)
    if @style == 'Led'
      frame {
        padding 0
        
        label {
          grid row: 0, column: 0, column_weight: 0
          text 'Spacing:'
        }
        spinbox {
          grid row: 0, column: 1
          from 1
          to 72
          text <=> [self, :led_spacing]
        }
        
        checkbutton {
          grid row: 0, column: 2
          variable <=> [self, :led_round_corner]
        }
        label {
          grid row: 0, column: 3
          text 'Round Corner'
          
          on('Button-1') do
            self.led_round_corner = !led_round_corner
          end
        }
      }
    elsif @style == 'Sketch'
      frame {
        padding 0
        
        label {
          grid row: 0, column: 0, column_weight: 0
          text 'Line:'
        }
        spinbox {
          grid row: 0, column: 1
          from 1
          to 72
          text <=> [self, :sketch_line]
        }
      }
    else
      frame { # filler
        padding 0
        height 0
        width 0
      }
    end
  }
end

#collection_optionsObject



33
34
35
# File 'app/cryptopunks_gui.rb', line 33

def collection_options
  @collections_map.keys
end

#create_guiObject



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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'app/cryptopunks_gui.rb', line 151

def create_gui
  @root = root {
    title 'CryptoPunks GUI'
    iconphoto File.expand_path('../icons/cryptopunks-gui.png', __dir__)
    
    frame {
      label {
        text 'Collection:'
      }
      combobox {
        readonly true
        text <=> [self, :collection]
      }
      
      label {
        text 'Image Index:'
      }
      @image_index_spinbox = spinbox {
        from 0
        to @images[@collection].size - 1
        text <=> [self, :image_index]
      }
      
      label {
        text 'Zoom:'
      }
      spinbox {
        from 1
        to 72
        text <=> [self, :zoom]
      }
      
      label {
        text 'Palette:'
      }
      combobox {
        readonly true
        text <=> [self, :palette]
      }
      
      label {
        text 'Style:'
      }
      combobox {
        readonly true
        text <=> [self, :style, after_write: ->(val) {add_style_options}]
      }
      
      @style_options_frame = frame {
        padding 0
      }
      
      frame {
        padding 0
        
        checkbutton {
          grid row: 0, column: 0, column_weight: 0
          variable <=> [self, :mirror]
        }
        label {
          grid row: 0, column: 1
          text 'Mirror'
          
          on('Button-1') do
            self.mirror = !mirror
          end
        }
        
        checkbutton {
          grid row: 0, column: 2
          variable <=> [self, :flip]
        }
        label {
          grid row: 0, column: 3
          text 'Flip'
          
          on('Button-1') do
            self.flip = !flip
          end
        }
      }
      
      label {
        text 'Output Location:'
      }
      frame {
        padding 0
        
        @output_location_entry = entry {
          grid row: 0, column: 0
          readonly true
          width 47
        }
        button {
          grid row: 0, column: 1
          text '...'
          width 1.1
          
          on('command') do
            new_punk_directory = choose_directory(parent: @root)
            unless new_punk_directory.to_s.empty?
              @punk_directory = new_punk_directory
              @punk_config[:punk_directory] = @punk_directory
              save_config
              generate_image
            end
          end
        }
      }
      
      @image_label = label {
        grid row_weight: 1
      }
    }
  }
end

#generate_imageObject



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/cryptopunks_gui.rb', line 118

def generate_image
  initialize_collection
  return if @image_index.to_i > @images[@collection].size
  image_location = File.join(@punk_directory, "#{@collection.gsub(' ', '').downcase}-#{@image_index}#{"x#{@zoom}" if @zoom.to_i > 1}#{"-#{@palette.underscore}" if @palette != PALETTES.first}#{"-#{@style.underscore}" if @style != STYLES.first}.png")
  puts "Writing punk image to #{image_location}"
  selected_punk = @images[@collection][@image_index.to_i]
  selected_punk = selected_punk.change_palette8bit(Palette8bit.const_get(@palette.gsub(' ', '_').upcase.to_sym)) if @palette != PALETTES.first
  @original_zoom = @zoom
  if @previous_collection && @collection != @previous_collection && @collections_map[@collection][:width] != @collections_map[@previous_collection][:width]
    @zoom = @collections_map[@collection][:default_zoom]
  end
  if @style != STYLES.first
    style_options = {}
    if @style == 'Led'
      style_options[:spacing] = @led_spacing.to_i
      style_options[:round_corner] = @led_round_corner
    end
    if @style == 'Sketch'
      style_options[:line] = @sketch_line.to_i
    end
    selected_punk = selected_punk.send(@style.underscore, @zoom.to_i, **style_options)
  end
  selected_punk = selected_punk.mirror if @mirror
  selected_punk = selected_punk.flip if @flip
  selected_punk = selected_punk.zoom(@zoom.to_i) if @style == STYLES.first
  selected_punk.save(image_location)
  @image_label.image = image_location
  @output_location_entry.text = image_location
  @previous_style = @style
  @previous_collection = @collection
  notify_observers(:zoom) if @zoom != @original_zoom
end

#initialize_collectionObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'app/cryptopunks_gui.rb', line 66

def initialize_collection
  return if @collection && @collection == @last_collection
  @collection ||= @collections_map.keys.first
  url = @collections_map[@collection][:url]
  width = @collections_map[@collection][:width]
  height = @collections_map[@collection][:height]
  @punk_file = File.join(@punk_config_directory, File.basename(url, '.png'))
  File.write(@punk_file, Net::HTTP.get(URI(url))) unless File.exist?(@punk_file)
  @images ||= {}
  @images[@collection] ||= Punks::Image::Composite.read(@punk_file, width: width, height: height)
  @last_collection = @collection
  self.image_index = 0
  @image_index_spinbox.to = @images[@collection].size - 1 if @image_index_spinbox
end

#initialize_collections_mapObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'app/cryptopunks_gui.rb', line 50

def initialize_collections_map
  begin
    http_response = Net::HTTP.get_response(URI(COLLECTIONS_YAML_URL))
    if http_response.is_a?(Net::HTTPSuccess)
      @collections_map = YAML.load(http_response.body)
    else
      raise "code: #{http_response.code} message: #{http_response.message}"
    end
  rescue StandardError, SocketError => e
    puts "Failed to utilize collection YAML from: #{COLLECTIONS_YAML_URL}"
    puts e.full_message
    puts "Utilizing local collection YAML instead: #{COLLECTIONS_YAML_PATH}"
    @collections_map = YAML.load(File.read(COLLECTIONS_YAML_PATH))
  end
end

#initialize_defaultsObject



92
93
94
95
96
97
98
99
100
101
102
# File 'app/cryptopunks_gui.rb', line 92

def initialize_defaults
  @collection = @collections_map.keys.first
  @zoom = 12
  @palette = PALETTES.first
  @style = STYLES.first
  @led_spacing = 2
  @led_round_corner = false
  @sketch_line = 1
  @mirror = false
  @flip = false
end

#initialize_punk_directoryObject



45
46
47
48
# File 'app/cryptopunks_gui.rb', line 45

def initialize_punk_directory
  @punk_directory = @punk_config_directory = File.join(Dir.home, 'cryptopunks')
  FileUtils.mkdir_p(@punk_directory)
end

#load_configObject



81
82
83
84
85
86
# File 'app/cryptopunks_gui.rb', line 81

def load_config
  @punk_config_file = File.join(@punk_config_directory, 'cryptopunks.yml')
  FileUtils.touch(@punk_config_file)
  @punk_config = YAML.load(File.read(@punk_config_file)) || {punk_directory: @punk_directory}
  @punk_directory = @punk_config[:punk_directory]
end

#observe_image_attribute_changesObject



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'app/cryptopunks_gui.rb', line 104

def observe_image_attribute_changes
  observer = Glimmer::DataBinding::Observer.proc { generate_image }
  observer.observe(self, :collection)
  observer.observe(self, :image_index)
  observer.observe(self, :zoom)
  observer.observe(self, :palette)
  observer.observe(self, :style)
  observer.observe(self, :led_spacing)
  observer.observe(self, :led_round_corner)
  observer.observe(self, :sketch_line)
  observer.observe(self, :mirror)
  observer.observe(self, :flip)
end

#palette_optionsObject



37
38
39
# File 'app/cryptopunks_gui.rb', line 37

def palette_options
  PALETTES
end

#save_configObject



88
89
90
# File 'app/cryptopunks_gui.rb', line 88

def save_config
  File.write(@punk_config_file, YAML.dump(@punk_config))
end

#style_optionsObject



41
42
43
# File 'app/cryptopunks_gui.rb', line 41

def style_options
  STYLES
end