cryptopunks-gui 0.0.11 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/LICENSE.txt +1 -1
- data/README.md +6 -6
- data/VERSION +1 -1
- data/app/cryptopunks_gui.rb +17 -298
- data/app/model/image.rb +187 -0
- data/app/view/help_dialog.rb +31 -0
- data/app/view/image_frame.rb +145 -0
- data/app/view/menu_bar.rb +88 -0
- data/app/view/preferences_dialog.rb +174 -0
- data/app/view/style_options_frame.rb +60 -0
- data/cryptopunks-gui.gemspec +14 -8
- metadata +15 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aba61bde681e3e74f5eaeb12aa80e4ceb1dea6b3465e88909adbfef8815e0be1
|
|
4
|
+
data.tar.gz: 970ef62ad8b5620c9da4aadc3b33e700d82a54d80597947d2f481cf85e7476cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7d87cbd6ac7f572aafca0b687f6dd0c95ad74c2a96b09d225da75d14d700572243fbe9611590db7a2fe833798a47595fe6aca003a4675b50f80a4009de394779
|
|
7
|
+
data.tar.gz: 5decb6852dc84e4ec00078d9779681dc8800fd9697d5fd9e2c01d562292ae86652dd274d9bfb3d7f7acdc44c47e99d96f6369d5384abfa462a32accdd548504d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 0.0.15
|
|
4
|
+
|
|
5
|
+
- Upgrade to glimmer-dsl-tk 0.0.49
|
|
6
|
+
|
|
7
|
+
## 0.0.14
|
|
8
|
+
|
|
9
|
+
- Fix PNG signature not found issue on Windows by writing images as binary files (`chunky_png-1.4.0/lib/chunky_png/datastream.rb:107:in verify_signature!': PNG signature not found, found "\\x89PNG\\r\\r\\n\\x1A" instead of "\\x89PNG\\r\\n\\x1A\\n"! (ChunkyPNG::SignatureMismatch)`)
|
|
10
|
+
- Fix regression issue with image index allowed out of bounds when changing to a collection with less images than current collection
|
|
11
|
+
|
|
12
|
+
## 0.0.13
|
|
13
|
+
|
|
14
|
+
- Support older Ruby versions down to 2.7.2 by fixing an issue with not having `#name` method on `Symbol`
|
|
15
|
+
|
|
16
|
+
## 0.0.12
|
|
17
|
+
|
|
18
|
+
- Upgrade to glimmer-dsl-tk 0.0.46
|
|
19
|
+
- File & Help Menus
|
|
20
|
+
- Update COLLECTIONS_YAML_URL to point to cryptopunksnotdead repository (recently moved there)
|
|
21
|
+
- Add 'Mirror', 'Flip', 'Led' and 'Sketch' details (e.g. spacing or line) to output file name (e.g. '...-mirror.png')
|
|
22
|
+
- Fix issue with allowing out of bounds image index when entering index that is equal to count of images in a collection (off by 1 error)
|
|
23
|
+
- Fix written file name for downloaded sprites (was excluding .png before)
|
|
24
|
+
- Fix issue with @punk_directory mistakenly referenced after being removed through refactoring
|
|
25
|
+
|
|
3
26
|
## 0.0.11
|
|
4
27
|
|
|
5
|
-
- Support configuring default collections through a web hosted yaml file at: https://raw.githubusercontent.com/
|
|
28
|
+
- Support configuring default collections through a web hosted yaml file at: https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks-gui/master/cryptopunks-collections.yml
|
|
6
29
|
- New Green Punks, Clown Punks, and Bubble Gum Punks collections
|
|
7
30
|
|
|
8
31
|
## 0.0.10
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# <img src="https://raw.githubusercontent.com/
|
|
1
|
+
# <img src="https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks-gui/master/icons/cryptopunks-gui.png" height=85 /> CryptoPunks GUI 0.0.15
|
|
2
2
|
## Simplified Minting
|
|
3
3
|
[](http://badge.fury.io/rb/cryptopunks-gui)
|
|
4
4
|
|
|
5
|
-
This is a Graphical User Interface for the
|
|
5
|
+
This is a Graphical User Interface for the [cryptopunks Ruby gem](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks).
|
|
6
6
|
|
|
7
7
|
It automatically downloads image collection sprites on first use (e.g. `punks.png` from https://github.com/larvalabs/cryptopunks).
|
|
8
8
|
|
|
@@ -18,14 +18,14 @@ Minted cryptopunks are stored at `~/cryptopunks/` by default ([output location c
|
|
|
18
18
|
|
|
19
19
|
## Setup
|
|
20
20
|
|
|
21
|
-
You can use CryptoPunks GUI via gem or via cloning repository.
|
|
21
|
+
You can use CryptoPunks GUI via gem or via cloning repository (if you encounter any issues, please try older versions of the gem and report the issues encountered).
|
|
22
22
|
|
|
23
23
|
### Gem
|
|
24
24
|
|
|
25
25
|
Run:
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
gem install cryptopunks-gui -v0.0.
|
|
28
|
+
gem install cryptopunks-gui -v0.0.15
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Afterwards, run app via:
|
|
@@ -39,7 +39,7 @@ cryptopunks-gui
|
|
|
39
39
|
Clone repository:
|
|
40
40
|
|
|
41
41
|
```
|
|
42
|
-
git clone https://github.com/
|
|
42
|
+
git clone https://github.com/cryptopunksnotdead/cryptopunks-gui.git
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
Enter directory:
|
|
@@ -236,7 +236,7 @@ You may select a new output location by clicking on the `...` button.
|
|
|
236
236
|
|
|
237
237
|
[MIT](LICENSE.txt)
|
|
238
238
|
|
|
239
|
-
Copyright (c) 2021 - Cryptopunks GUI by [
|
|
239
|
+
Copyright (c) 2021 - Cryptopunks GUI by [Crypto Punk's Not Dead](https://github.com/cryptopunksnotdead)
|
|
240
240
|
|
|
241
241
|
--
|
|
242
242
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.15
|
data/app/cryptopunks_gui.rb
CHANGED
|
@@ -1,323 +1,42 @@
|
|
|
1
1
|
require 'glimmer-dsl-tk'
|
|
2
|
+
require 'glimmer/data_binding/observer'
|
|
2
3
|
require 'cryptopunks'
|
|
3
4
|
require 'facets'
|
|
4
5
|
require 'fileutils'
|
|
5
6
|
require 'net/http'
|
|
6
7
|
require 'uri'
|
|
7
|
-
require 'glimmer/data_binding/observer'
|
|
8
8
|
require 'yaml'
|
|
9
9
|
require 'puts_debuggerer'
|
|
10
10
|
|
|
11
|
+
require_relative 'model/image'
|
|
12
|
+
require_relative 'view/menu_bar'
|
|
13
|
+
require_relative 'view/image_frame'
|
|
14
|
+
require_relative 'view/style_options_frame'
|
|
15
|
+
|
|
11
16
|
class CryptopunksGui
|
|
12
17
|
include Glimmer
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
COLLECTIONS_YAML_URL = 'https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/cryptopunks-collections.yml'
|
|
17
|
-
COLLECTIONS_YAML_PATH = File.expand_path('../cryptopunks-collections.yml', __dir__)
|
|
18
|
-
|
|
19
|
-
attr_accessor :collection, :image_index, :zoom, :palette, :style, :led_spacing, :led_round_corner, :sketch_line, :flip, :mirror
|
|
18
|
+
include View::MenuBar
|
|
19
|
+
include View::ImageFrame
|
|
20
|
+
include View::StyleOptionsFrame
|
|
20
21
|
|
|
21
22
|
def initialize
|
|
22
|
-
|
|
23
|
-
initialize_collections_map
|
|
24
|
-
initialize_collection
|
|
25
|
-
load_config
|
|
26
|
-
initialize_defaults
|
|
27
|
-
observe_image_attribute_changes
|
|
23
|
+
@image = Model::Image.new
|
|
28
24
|
create_gui
|
|
29
|
-
|
|
30
|
-
@root.open
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def collection_options
|
|
34
|
-
@collections_map.keys
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def palette_options
|
|
38
|
-
PALETTES
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def style_options
|
|
42
|
-
STYLES
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def initialize_punk_directory
|
|
46
|
-
@punk_directory = @punk_config_directory = File.join(Dir.home, 'cryptopunks')
|
|
47
|
-
FileUtils.mkdir_p(@punk_directory)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def initialize_collections_map
|
|
51
|
-
begin
|
|
52
|
-
http_response = Net::HTTP.get_response(URI(COLLECTIONS_YAML_URL))
|
|
53
|
-
if http_response.is_a?(Net::HTTPSuccess)
|
|
54
|
-
@collections_map = YAML.load(http_response.body)
|
|
55
|
-
else
|
|
56
|
-
raise "code: #{http_response.code} message: #{http_response.message}"
|
|
57
|
-
end
|
|
58
|
-
rescue StandardError, SocketError => e
|
|
59
|
-
puts "Failed to utilize collection YAML from: #{COLLECTIONS_YAML_URL}"
|
|
60
|
-
puts e.full_message
|
|
61
|
-
puts "Utilizing local collection YAML instead: #{COLLECTIONS_YAML_PATH}"
|
|
62
|
-
@collections_map = YAML.load(File.read(COLLECTIONS_YAML_PATH))
|
|
63
|
-
end
|
|
25
|
+
@image.image_index = 0
|
|
64
26
|
end
|
|
65
27
|
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
@collection ||= @collections_map.keys.first
|
|
69
|
-
url = @collections_map[@collection][:url]
|
|
70
|
-
width = @collections_map[@collection][:width]
|
|
71
|
-
height = @collections_map[@collection][:height]
|
|
72
|
-
@punk_file = File.join(@punk_config_directory, File.basename(url, '.png'))
|
|
73
|
-
File.write(@punk_file, Net::HTTP.get(URI(url))) unless File.exist?(@punk_file)
|
|
74
|
-
@images ||= {}
|
|
75
|
-
@images[@collection] ||= Punks::Image::Composite.read(@punk_file, width: width, height: height)
|
|
76
|
-
@last_collection = @collection
|
|
77
|
-
self.image_index = 0
|
|
78
|
-
@image_index_spinbox.to = @images[@collection].size - 1 if @image_index_spinbox
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def load_config
|
|
82
|
-
@punk_config_file = File.join(@punk_config_directory, 'cryptopunks.yml')
|
|
83
|
-
FileUtils.touch(@punk_config_file)
|
|
84
|
-
@punk_config = YAML.load(File.read(@punk_config_file)) || {punk_directory: @punk_directory}
|
|
85
|
-
@punk_directory = @punk_config[:punk_directory]
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def save_config
|
|
89
|
-
File.write(@punk_config_file, YAML.dump(@punk_config))
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def initialize_defaults
|
|
93
|
-
@collection = @collections_map.keys.first
|
|
94
|
-
@zoom = 12
|
|
95
|
-
@palette = PALETTES.first
|
|
96
|
-
@style = STYLES.first
|
|
97
|
-
@led_spacing = 2
|
|
98
|
-
@led_round_corner = false
|
|
99
|
-
@sketch_line = 1
|
|
100
|
-
@mirror = false
|
|
101
|
-
@flip = false
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def observe_image_attribute_changes
|
|
105
|
-
observer = Glimmer::DataBinding::Observer.proc { generate_image }
|
|
106
|
-
observer.observe(self, :collection)
|
|
107
|
-
observer.observe(self, :image_index)
|
|
108
|
-
observer.observe(self, :zoom)
|
|
109
|
-
observer.observe(self, :palette)
|
|
110
|
-
observer.observe(self, :style)
|
|
111
|
-
observer.observe(self, :led_spacing)
|
|
112
|
-
observer.observe(self, :led_round_corner)
|
|
113
|
-
observer.observe(self, :sketch_line)
|
|
114
|
-
observer.observe(self, :mirror)
|
|
115
|
-
observer.observe(self, :flip)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def generate_image
|
|
119
|
-
initialize_collection
|
|
120
|
-
return if @image_index.to_i > @images[@collection].size
|
|
121
|
-
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")
|
|
122
|
-
puts "Writing punk image to #{image_location}"
|
|
123
|
-
selected_punk = @images[@collection][@image_index.to_i]
|
|
124
|
-
selected_punk = selected_punk.change_palette8bit(Palette8bit.const_get(@palette.gsub(' ', '_').upcase.to_sym)) if @palette != PALETTES.first
|
|
125
|
-
@original_zoom = @zoom
|
|
126
|
-
if @previous_collection && @collection != @previous_collection && @collections_map[@collection][:width] != @collections_map[@previous_collection][:width]
|
|
127
|
-
@zoom = @collections_map[@collection][:default_zoom]
|
|
128
|
-
end
|
|
129
|
-
if @style != STYLES.first
|
|
130
|
-
style_options = {}
|
|
131
|
-
if @style == 'Led'
|
|
132
|
-
style_options[:spacing] = @led_spacing.to_i
|
|
133
|
-
style_options[:round_corner] = @led_round_corner
|
|
134
|
-
end
|
|
135
|
-
if @style == 'Sketch'
|
|
136
|
-
style_options[:line] = @sketch_line.to_i
|
|
137
|
-
end
|
|
138
|
-
selected_punk = selected_punk.send(@style.underscore, @zoom.to_i, **style_options)
|
|
139
|
-
end
|
|
140
|
-
selected_punk = selected_punk.mirror if @mirror
|
|
141
|
-
selected_punk = selected_punk.flip if @flip
|
|
142
|
-
selected_punk = selected_punk.zoom(@zoom.to_i) if @style == STYLES.first
|
|
143
|
-
selected_punk.save(image_location)
|
|
144
|
-
@image_label.image = image_location
|
|
145
|
-
@output_location_entry.text = image_location
|
|
146
|
-
@previous_style = @style
|
|
147
|
-
@previous_collection = @collection
|
|
148
|
-
notify_observers(:zoom) if @zoom != @original_zoom
|
|
28
|
+
def launch
|
|
29
|
+
@root.open
|
|
149
30
|
end
|
|
150
31
|
|
|
151
32
|
def create_gui
|
|
152
|
-
@root = root {
|
|
33
|
+
@root = root { |root_proxy|
|
|
153
34
|
title 'CryptoPunks GUI'
|
|
154
35
|
iconphoto File.expand_path('../icons/cryptopunks-gui.png', __dir__)
|
|
155
36
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
combobox {
|
|
161
|
-
readonly true
|
|
162
|
-
text <=> [self, :collection]
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
label {
|
|
166
|
-
text 'Image Index:'
|
|
167
|
-
}
|
|
168
|
-
@image_index_spinbox = spinbox {
|
|
169
|
-
from 0
|
|
170
|
-
to @images[@collection].size - 1
|
|
171
|
-
text <=> [self, :image_index]
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
label {
|
|
175
|
-
text 'Zoom:'
|
|
176
|
-
}
|
|
177
|
-
spinbox {
|
|
178
|
-
from 1
|
|
179
|
-
to 72
|
|
180
|
-
text <=> [self, :zoom]
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
label {
|
|
184
|
-
text 'Palette:'
|
|
185
|
-
}
|
|
186
|
-
combobox {
|
|
187
|
-
readonly true
|
|
188
|
-
text <=> [self, :palette]
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
label {
|
|
192
|
-
text 'Style:'
|
|
193
|
-
}
|
|
194
|
-
combobox {
|
|
195
|
-
readonly true
|
|
196
|
-
text <=> [self, :style, after_write: ->(val) {add_style_options}]
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
@style_options_frame = frame {
|
|
200
|
-
padding 0
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
frame {
|
|
204
|
-
padding 0
|
|
205
|
-
|
|
206
|
-
checkbutton {
|
|
207
|
-
grid row: 0, column: 0, column_weight: 0
|
|
208
|
-
variable <=> [self, :mirror]
|
|
209
|
-
}
|
|
210
|
-
label {
|
|
211
|
-
grid row: 0, column: 1
|
|
212
|
-
text 'Mirror'
|
|
213
|
-
|
|
214
|
-
on('Button-1') do
|
|
215
|
-
self.mirror = !mirror
|
|
216
|
-
end
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
checkbutton {
|
|
220
|
-
grid row: 0, column: 2
|
|
221
|
-
variable <=> [self, :flip]
|
|
222
|
-
}
|
|
223
|
-
label {
|
|
224
|
-
grid row: 0, column: 3
|
|
225
|
-
text 'Flip'
|
|
226
|
-
|
|
227
|
-
on('Button-1') do
|
|
228
|
-
self.flip = !flip
|
|
229
|
-
end
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
label {
|
|
234
|
-
text 'Output Location:'
|
|
235
|
-
}
|
|
236
|
-
frame {
|
|
237
|
-
padding 0
|
|
238
|
-
|
|
239
|
-
@output_location_entry = entry {
|
|
240
|
-
grid row: 0, column: 0
|
|
241
|
-
readonly true
|
|
242
|
-
width 47
|
|
243
|
-
}
|
|
244
|
-
button {
|
|
245
|
-
grid row: 0, column: 1
|
|
246
|
-
text '...'
|
|
247
|
-
width 1.1
|
|
248
|
-
|
|
249
|
-
on('command') do
|
|
250
|
-
new_punk_directory = choose_directory(parent: @root)
|
|
251
|
-
unless new_punk_directory.to_s.empty?
|
|
252
|
-
@punk_directory = new_punk_directory
|
|
253
|
-
@punk_config[:punk_directory] = @punk_directory
|
|
254
|
-
save_config
|
|
255
|
-
generate_image
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
@image_label = label {
|
|
262
|
-
grid row_weight: 1
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
def add_style_options
|
|
269
|
-
@style_options_frame.content {
|
|
270
|
-
@style_options_frame.children.each(&:destroy)
|
|
271
|
-
if @style == 'Led'
|
|
272
|
-
frame {
|
|
273
|
-
padding 0
|
|
274
|
-
|
|
275
|
-
label {
|
|
276
|
-
grid row: 0, column: 0, column_weight: 0
|
|
277
|
-
text 'Spacing:'
|
|
278
|
-
}
|
|
279
|
-
spinbox {
|
|
280
|
-
grid row: 0, column: 1
|
|
281
|
-
from 1
|
|
282
|
-
to 72
|
|
283
|
-
text <=> [self, :led_spacing]
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
checkbutton {
|
|
287
|
-
grid row: 0, column: 2
|
|
288
|
-
variable <=> [self, :led_round_corner]
|
|
289
|
-
}
|
|
290
|
-
label {
|
|
291
|
-
grid row: 0, column: 3
|
|
292
|
-
text 'Round Corner'
|
|
293
|
-
|
|
294
|
-
on('Button-1') do
|
|
295
|
-
self.led_round_corner = !led_round_corner
|
|
296
|
-
end
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
elsif @style == 'Sketch'
|
|
300
|
-
frame {
|
|
301
|
-
padding 0
|
|
302
|
-
|
|
303
|
-
label {
|
|
304
|
-
grid row: 0, column: 0, column_weight: 0
|
|
305
|
-
text 'Line:'
|
|
306
|
-
}
|
|
307
|
-
spinbox {
|
|
308
|
-
grid row: 0, column: 1
|
|
309
|
-
from 1
|
|
310
|
-
to 72
|
|
311
|
-
text <=> [self, :sketch_line]
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
else
|
|
315
|
-
frame { # filler
|
|
316
|
-
padding 0
|
|
317
|
-
height 0
|
|
318
|
-
width 0
|
|
319
|
-
}
|
|
320
|
-
end
|
|
37
|
+
cryptopunks_gui_menu_bar(root: root_proxy, image: @image)
|
|
38
|
+
|
|
39
|
+
image_frame(root: root_proxy, image: @image)
|
|
321
40
|
}
|
|
322
41
|
end
|
|
323
42
|
end
|
data/app/model/image.rb
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
class CryptopunksGui
|
|
2
|
+
module Model
|
|
3
|
+
class Image
|
|
4
|
+
PALETTES = ['Standard'] + (Palette8bit.constants).map(&:to_s).map {|palette| palette.split('_').map(&:capitalize).join(' ')}.reject { |palette| palette.include?(' ') }.sort
|
|
5
|
+
STYLES = ['Normal', 'Led', 'Sketch']
|
|
6
|
+
OUTPUT_LOCATION_DEFAULT = File.join(Dir.home, 'cryptopunks')
|
|
7
|
+
CONFIG_FILE = File.join(OUTPUT_LOCATION_DEFAULT, 'cryptopunks.yml')
|
|
8
|
+
COLLECTIONS_YAML_PATH = File.join(OUTPUT_LOCATION_DEFAULT, 'cryptopunks-collections.yml')
|
|
9
|
+
COLLECTIONS_YAML_URL = 'https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks-gui/master/cryptopunks-collections.yml'
|
|
10
|
+
COLLECTIONS_YAML_REPO_PATH = File.expand_path('../../cryptopunks-collections.yml', __dir__)
|
|
11
|
+
|
|
12
|
+
attr_accessor :collection, :image_index, :zoom, :palette, :style, :led_spacing, :led_round_corner, :sketch_line, :flip, :mirror,
|
|
13
|
+
:collection_size, :collections_map, :images, :image_location, :output_location, :config
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
initialize_output_location
|
|
17
|
+
initialize_collections_map
|
|
18
|
+
initialize_collection
|
|
19
|
+
load_config
|
|
20
|
+
initialize_defaults
|
|
21
|
+
observe_image_attribute_changes
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def collection_options
|
|
25
|
+
@collections_map.keys.select {|collection_name| @collections_map[collection_name][:enabled]}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def palette_options
|
|
29
|
+
PALETTES
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def style_options
|
|
33
|
+
STYLES
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def initialize_output_location
|
|
37
|
+
@output_location = OUTPUT_LOCATION_DEFAULT
|
|
38
|
+
FileUtils.mkdir_p(@output_location)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize_collections_map(reset: false)
|
|
42
|
+
FileUtils.touch(COLLECTIONS_YAML_PATH)
|
|
43
|
+
@collections_map = reset ? {} : (YAML.load(File.read(COLLECTIONS_YAML_PATH)) || {})
|
|
44
|
+
new_collections_map = {}
|
|
45
|
+
begin
|
|
46
|
+
http_response = Net::HTTP.get_response(URI(COLLECTIONS_YAML_URL))
|
|
47
|
+
if http_response.is_a?(Net::HTTPSuccess)
|
|
48
|
+
new_collections_map = YAML.load(http_response.body)
|
|
49
|
+
else
|
|
50
|
+
raise "code: #{http_response.code} message: #{http_response.message}"
|
|
51
|
+
end
|
|
52
|
+
rescue StandardError, SocketError => e
|
|
53
|
+
puts "Failed to utilize collection YAML from: #{COLLECTIONS_YAML_URL}"
|
|
54
|
+
puts e.full_message
|
|
55
|
+
puts "Utilizing local collection YAML instead: #{COLLECTIONS_YAML_REPO_PATH}"
|
|
56
|
+
new_collections_map = YAML.load(File.read(COLLECTIONS_YAML_REPO_PATH)) rescue {}
|
|
57
|
+
end
|
|
58
|
+
@collections_map_observers ||= {}
|
|
59
|
+
new_collections_map.each do |collection_name, collection_options|
|
|
60
|
+
@collections_map[collection_name] ||= {}
|
|
61
|
+
original_collections_map_for_collection = @collections_map[collection_name]
|
|
62
|
+
@collections_map[collection_name] = @collections_map[collection_name]
|
|
63
|
+
@collections_map[collection_name].reverse_merge!(collection_options)
|
|
64
|
+
@collections_map[collection_name][:enabled] = true unless @collections_map[collection_name].has_key?(:enabled)
|
|
65
|
+
@collections_map_observers[collection_name] ||= Glimmer::DataBinding::Observer.proc { |value, key|
|
|
66
|
+
if key == :enabled
|
|
67
|
+
self.collection = @collections_map.find { |name, options| options[:enabled] }.first if key == :enabled && value == false && @collection == collection_name
|
|
68
|
+
notify_observers(:collection_options)
|
|
69
|
+
end
|
|
70
|
+
save_collections_map
|
|
71
|
+
}.tap {|o| o.observe(original_collections_map_for_collection)}
|
|
72
|
+
end
|
|
73
|
+
@collections_map_observer ||= Glimmer::DataBinding::Observer.proc { |collection_options, collection_name|
|
|
74
|
+
if collection_options.nil?
|
|
75
|
+
self.collection = @collections_map.find { |name, options| options[:enabled] }.first if @collection == collection_name
|
|
76
|
+
self.collection = collection_name if @collections_map.select { |name, options| options[:enabled] }.count == 0
|
|
77
|
+
end
|
|
78
|
+
notify_observers(:collection_options)
|
|
79
|
+
save_collections_map
|
|
80
|
+
}.tap {|o| o.observe(@collections_map)}
|
|
81
|
+
save_collections_map
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def save_collections_map
|
|
85
|
+
normalized_collections_map = Hash[@collections_map.map {|k,v| [k, v.to_h]}]
|
|
86
|
+
File.write(COLLECTIONS_YAML_PATH, YAML.dump(normalized_collections_map))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def initialize_collection
|
|
90
|
+
return if @collection && @collection == @last_collection
|
|
91
|
+
@collection ||= @collections_map.keys.first
|
|
92
|
+
url = @collections_map[@collection][:url]
|
|
93
|
+
width = @collections_map[@collection][:width]
|
|
94
|
+
height = @collections_map[@collection][:height]
|
|
95
|
+
@image_file = File.join(OUTPUT_LOCATION_DEFAULT, File.basename(url))
|
|
96
|
+
File.binwrite(@image_file, Net::HTTP.get(URI(url))) unless File.exist?(@image_file)
|
|
97
|
+
@images ||= {}
|
|
98
|
+
@images[@collection] ||= Punks::Image::Composite.read(@image_file, width: width, height: height)
|
|
99
|
+
@last_collection = @collection
|
|
100
|
+
self.image_index = 0
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def load_config
|
|
104
|
+
FileUtils.touch(CONFIG_FILE)
|
|
105
|
+
@config = YAML.load(File.read(CONFIG_FILE)) || {}
|
|
106
|
+
@output_location = @config[:output_location]
|
|
107
|
+
@config[:output_location] = @output_location = OUTPUT_LOCATION_DEFAULT if @output_location.nil?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def save_config
|
|
111
|
+
File.write(CONFIG_FILE, YAML.dump(@config))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def initialize_defaults
|
|
115
|
+
@collection = @collections_map.keys.first
|
|
116
|
+
@zoom = 12
|
|
117
|
+
@palette = PALETTES.first
|
|
118
|
+
@style = STYLES.first
|
|
119
|
+
@led_spacing = 2
|
|
120
|
+
@led_round_corner = false
|
|
121
|
+
@sketch_line = 1
|
|
122
|
+
@mirror = false
|
|
123
|
+
@flip = false
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def observe_image_attribute_changes
|
|
127
|
+
observer = Glimmer::DataBinding::Observer.proc { generate_image }
|
|
128
|
+
observer.observe(self, :collection)
|
|
129
|
+
observer.observe(self, :image_index)
|
|
130
|
+
observer.observe(self, :zoom)
|
|
131
|
+
observer.observe(self, :palette)
|
|
132
|
+
observer.observe(self, :style)
|
|
133
|
+
observer.observe(self, :led_spacing)
|
|
134
|
+
observer.observe(self, :led_round_corner)
|
|
135
|
+
observer.observe(self, :sketch_line)
|
|
136
|
+
observer.observe(self, :mirror)
|
|
137
|
+
observer.observe(self, :flip)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def generate_image
|
|
141
|
+
initialize_collection
|
|
142
|
+
return if @image_index.to_i >= @images[@collection].size
|
|
143
|
+
new_image_location = File.join(@output_location, "#{@collection.gsub(' ', '').downcase}-#{@image_index}#{"x#{@zoom}" if @zoom.to_i > 1}#{"-#{@palette.underscore}" if @palette != PALETTES.first}#{"-#{@style.underscore}" if @style != STYLES.first}#{"-spacing#{@led_spacing.to_i}" if @style == 'Led'}#{'-round-corner' if @style == 'Led' && @led_round_corner}#{"-line#{@sketch_line.to_i}" if @style == 'Sketch'}#{'-mirror' if @mirror}#{'-flip' if @flip}.png")
|
|
144
|
+
puts "Writing punk image to #{new_image_location}"
|
|
145
|
+
selected_punk = @images[@collection][@image_index.to_i]
|
|
146
|
+
selected_punk = selected_punk.change_palette8bit(Palette8bit.const_get(@palette.gsub(' ', '_').upcase.to_sym)) if @palette != PALETTES.first
|
|
147
|
+
@original_zoom = @zoom
|
|
148
|
+
if @previous_collection && @collection != @previous_collection && @collections_map[@collection][:width] != @collections_map[@previous_collection][:width]
|
|
149
|
+
@zoom = @collections_map[@collection][:default_zoom]
|
|
150
|
+
end
|
|
151
|
+
if @style != STYLES.first
|
|
152
|
+
style_options = {}
|
|
153
|
+
if @style == 'Led'
|
|
154
|
+
style_options[:spacing] = @led_spacing.to_i
|
|
155
|
+
style_options[:round_corner] = @led_round_corner
|
|
156
|
+
end
|
|
157
|
+
if @style == 'Sketch'
|
|
158
|
+
style_options[:line] = @sketch_line.to_i
|
|
159
|
+
end
|
|
160
|
+
selected_punk = selected_punk.send(@style.underscore, @zoom.to_i, **style_options)
|
|
161
|
+
end
|
|
162
|
+
selected_punk = selected_punk.mirror if @mirror
|
|
163
|
+
selected_punk = selected_punk.flip if @flip
|
|
164
|
+
selected_punk = selected_punk.zoom(@zoom.to_i) if @style == STYLES.first
|
|
165
|
+
selected_punk.save(new_image_location)
|
|
166
|
+
self.image_location = new_image_location
|
|
167
|
+
notify_observers(:zoom) if @zoom != @original_zoom
|
|
168
|
+
@previous_style = @style
|
|
169
|
+
@previous_collection = @collection
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def change_output_location(new_output_location)
|
|
173
|
+
@output_location = new_output_location
|
|
174
|
+
@config[:output_location] = @output_location
|
|
175
|
+
save_config
|
|
176
|
+
generate_image
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def reset_output_location
|
|
180
|
+
@output_location = OUTPUT_LOCATION_DEFAULT
|
|
181
|
+
@config[:output_location] = @output_location
|
|
182
|
+
save_config
|
|
183
|
+
generate_image
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class CryptopunksGui
|
|
2
|
+
module View
|
|
3
|
+
module HelpDialog
|
|
4
|
+
def help_dialog(root: )
|
|
5
|
+
toplevel(root) {
|
|
6
|
+
title 'CryptoPunks GUI - README.md'
|
|
7
|
+
width 800
|
|
8
|
+
height 600
|
|
9
|
+
escapable true
|
|
10
|
+
|
|
11
|
+
help_dialog = text {
|
|
12
|
+
grid row: 0, column: 0, row_weight: 1, column_weight: 1
|
|
13
|
+
value help
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
help_dialog_yscrollbar = scrollbar {
|
|
17
|
+
grid row: 0, column: 1
|
|
18
|
+
orient 'vertical'
|
|
19
|
+
}
|
|
20
|
+
help_dialog.yscrollbar help_dialog_yscrollbar.tk
|
|
21
|
+
|
|
22
|
+
help_dialog_xscrollbar = scrollbar {
|
|
23
|
+
grid row: 1, column: 0, column_span: 2
|
|
24
|
+
orient 'horizontal'
|
|
25
|
+
}
|
|
26
|
+
help_dialog.xscrollbar help_dialog_xscrollbar.tk
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
class CryptopunksGui
|
|
2
|
+
module View
|
|
3
|
+
module ImageFrame
|
|
4
|
+
def image_frame(root: , image: )
|
|
5
|
+
image_label = output_location_entry = image_index_spinbox = style_options_container_frame = nil
|
|
6
|
+
|
|
7
|
+
frame {
|
|
8
|
+
label {
|
|
9
|
+
text 'Collection:'
|
|
10
|
+
}
|
|
11
|
+
combobox {
|
|
12
|
+
readonly true
|
|
13
|
+
values <= [image, :collection_options]
|
|
14
|
+
text <=> [image, :collection]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
label {
|
|
18
|
+
text 'Image Index:'
|
|
19
|
+
}
|
|
20
|
+
image_index_spinbox = spinbox {
|
|
21
|
+
from 0
|
|
22
|
+
to image.images[image.collection].size - 1
|
|
23
|
+
text <=> [image, :image_index]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
label {
|
|
27
|
+
text 'Zoom:'
|
|
28
|
+
}
|
|
29
|
+
spinbox {
|
|
30
|
+
from 1
|
|
31
|
+
to 72
|
|
32
|
+
text <=> [image, :zoom]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
label {
|
|
36
|
+
text 'Palette:'
|
|
37
|
+
}
|
|
38
|
+
combobox {
|
|
39
|
+
readonly true
|
|
40
|
+
text <=> [image, :palette]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
label {
|
|
44
|
+
text 'Style:'
|
|
45
|
+
}
|
|
46
|
+
combobox {
|
|
47
|
+
readonly true
|
|
48
|
+
text <=> [image, :style, after_write: ->(val) {add_style_options(style_options_container_frame: style_options_container_frame, image: image)}]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
style_options_container_frame = frame {
|
|
52
|
+
padding 0
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
frame {
|
|
56
|
+
padding 0
|
|
57
|
+
|
|
58
|
+
checkbutton {
|
|
59
|
+
grid row: 0, column: 0, column_weight: 0
|
|
60
|
+
variable <=> [image, :mirror]
|
|
61
|
+
}
|
|
62
|
+
label {
|
|
63
|
+
grid row: 0, column: 1
|
|
64
|
+
text 'Mirror'
|
|
65
|
+
|
|
66
|
+
on('Button-1') do
|
|
67
|
+
image.mirror = !image.mirror
|
|
68
|
+
end
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
checkbutton {
|
|
72
|
+
grid row: 0, column: 2
|
|
73
|
+
variable <=> [image, :flip]
|
|
74
|
+
}
|
|
75
|
+
label {
|
|
76
|
+
grid row: 0, column: 3
|
|
77
|
+
text 'Flip'
|
|
78
|
+
|
|
79
|
+
on('Button-1') do
|
|
80
|
+
image.flip = !image.flip
|
|
81
|
+
end
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
label {
|
|
86
|
+
text 'Output Location:'
|
|
87
|
+
}
|
|
88
|
+
frame {
|
|
89
|
+
padding 0
|
|
90
|
+
|
|
91
|
+
output_location_entry = entry {
|
|
92
|
+
grid row: 0, column: 0
|
|
93
|
+
readonly true
|
|
94
|
+
width 47
|
|
95
|
+
}
|
|
96
|
+
button {
|
|
97
|
+
grid row: 0, column: 1
|
|
98
|
+
text '...'
|
|
99
|
+
width 1.1
|
|
100
|
+
|
|
101
|
+
on('command') do
|
|
102
|
+
change_output_location(root: root, image: image)
|
|
103
|
+
end
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
image_label = label {
|
|
108
|
+
grid row_weight: 1
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
register_image_frame_observers(image_label: image_label, output_location_entry: output_location_entry, image_index_spinbox: image_index_spinbox, image: image)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def register_image_frame_observers(image_label: , output_location_entry: , image_index_spinbox: , image: )
|
|
116
|
+
Glimmer::DataBinding::Observer.proc do
|
|
117
|
+
image_label.image = output_location_entry.text = image.image_location
|
|
118
|
+
end.observe(image, :image_location)
|
|
119
|
+
|
|
120
|
+
Glimmer::DataBinding::Observer.proc do
|
|
121
|
+
image_index_spinbox.to = image.images[image.collection].size - 1
|
|
122
|
+
end.observe(image, :collection)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def add_style_options(style_options_container_frame: , image: )
|
|
126
|
+
style_options_container_frame.children.each(&:destroy)
|
|
127
|
+
style_options_container_frame.content {
|
|
128
|
+
case image.style
|
|
129
|
+
when 'Led'
|
|
130
|
+
led_style_options_frame(image: image)
|
|
131
|
+
when 'Sketch'
|
|
132
|
+
sketch_style_options_frame(image: image)
|
|
133
|
+
else
|
|
134
|
+
no_style_options_frame
|
|
135
|
+
end
|
|
136
|
+
}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def change_output_location(root: , image: )
|
|
140
|
+
new_output_location = choose_directory(parent: root)
|
|
141
|
+
image.change_output_location(new_output_location) unless new_output_location.to_s.empty?
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# require_relative 'preferences_dialog'
|
|
2
|
+
require_relative 'help_dialog'
|
|
3
|
+
|
|
4
|
+
class CryptopunksGui
|
|
5
|
+
module View
|
|
6
|
+
module MenuBar
|
|
7
|
+
# include View::PreferencesDialog
|
|
8
|
+
include View::HelpDialog
|
|
9
|
+
|
|
10
|
+
LICENSE = File.expand_path('../../LICENSE.txt', __dir__)
|
|
11
|
+
HELP = File.expand_path('../../README.md', __dir__)
|
|
12
|
+
|
|
13
|
+
def cryptopunks_gui_menu_bar(root: , image: )
|
|
14
|
+
menu_bar {
|
|
15
|
+
if OS.mac?
|
|
16
|
+
menu(:application) {
|
|
17
|
+
menu_item(:about, label: 'About') {
|
|
18
|
+
accelerator OS.mac? ? 'Command+Shift+A' : 'Control+Alt+A'
|
|
19
|
+
|
|
20
|
+
on('command') do
|
|
21
|
+
show_about_dialog(root: root)
|
|
22
|
+
end
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# menu_item(:preferences) {
|
|
26
|
+
# on('command') do
|
|
27
|
+
# preferences_dialog(root: root, image: image)
|
|
28
|
+
# end
|
|
29
|
+
# }
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
menu(label: 'File', underline: 0) {
|
|
34
|
+
menu_item(label: 'Change Output Location...', underline: 7) {
|
|
35
|
+
accelerator OS.mac? ? 'Command+O' : 'Control+O'
|
|
36
|
+
|
|
37
|
+
on('command') do
|
|
38
|
+
change_output_location(root: root, image: image) # assumes View::ImageFrame is mixed in
|
|
39
|
+
end
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
menu_item(label: 'Reset Output Location', underline: 0) {
|
|
43
|
+
on('command') do
|
|
44
|
+
image.reset_output_location
|
|
45
|
+
end
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
menu_item(:separator)
|
|
49
|
+
|
|
50
|
+
# menu_item(label: 'Preferences...', underline: 0) {
|
|
51
|
+
# on('command') do
|
|
52
|
+
# preferences_dialog(root: root, image: image)
|
|
53
|
+
# end
|
|
54
|
+
# }
|
|
55
|
+
|
|
56
|
+
menu_item(:separator)
|
|
57
|
+
|
|
58
|
+
menu_item(label: 'Exit', underline: 1) {
|
|
59
|
+
on('command') do
|
|
60
|
+
exit(0)
|
|
61
|
+
end
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
menu(label: 'Help') {
|
|
66
|
+
menu_item(:help) {
|
|
67
|
+
on('command') do
|
|
68
|
+
help_dialog(root: root)
|
|
69
|
+
end
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def show_about_dialog(root: )
|
|
76
|
+
message_box(parent: root, title: 'CryptoPunks GUI', message: "CryptoPunks GUI\n\n#{license}")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def license
|
|
80
|
+
@license ||= File.read(LICENSE)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def help
|
|
84
|
+
@help ||= File.read(HELP)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
class CryptopunksGui
|
|
2
|
+
module View
|
|
3
|
+
module PreferencesDialog
|
|
4
|
+
def preferences_dialog(root: , image: )
|
|
5
|
+
toplevel(root) {
|
|
6
|
+
title 'Preferences'
|
|
7
|
+
width 1280
|
|
8
|
+
height 700
|
|
9
|
+
escapable true
|
|
10
|
+
|
|
11
|
+
scrollbar_frame {
|
|
12
|
+
label {
|
|
13
|
+
grid row: 0, column: 0
|
|
14
|
+
text ''
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
label {
|
|
18
|
+
grid row: 0, column: 1
|
|
19
|
+
text 'Collection Name'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
label {
|
|
23
|
+
grid row: 0, column: 2
|
|
24
|
+
text 'URL'
|
|
25
|
+
width 82
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
label {
|
|
29
|
+
grid row: 0, column: 3
|
|
30
|
+
text 'Width'
|
|
31
|
+
width 3
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
label {
|
|
35
|
+
grid row: 0, column: 4
|
|
36
|
+
text 'Height'
|
|
37
|
+
width 3
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
label {
|
|
41
|
+
grid row: 0, column: 5
|
|
42
|
+
text "Default\nZoom"
|
|
43
|
+
width 3
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
label {
|
|
47
|
+
grid row: 0, column: 6, column_span: 3
|
|
48
|
+
text 'Actions'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
image.collections_map.each_with_index do |pair, index|
|
|
52
|
+
collection_name, collection_options = pair
|
|
53
|
+
row = index + 1
|
|
54
|
+
|
|
55
|
+
checkbutton { |cb|
|
|
56
|
+
grid row: row, column: 0
|
|
57
|
+
# TODO consider using hash_proxy object to bind more effectively
|
|
58
|
+
variable <= [image.collections_map[collection_name], :enabled]
|
|
59
|
+
|
|
60
|
+
on('command') do
|
|
61
|
+
collection_options[:enabled] = cb.variable
|
|
62
|
+
end
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
entry {
|
|
66
|
+
grid row: row, column: 1
|
|
67
|
+
text collection_name
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
entry {
|
|
71
|
+
grid row: row, column: 2
|
|
72
|
+
text collection_options[:url]
|
|
73
|
+
width 82
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
spinbox {
|
|
77
|
+
grid row: row, column: 3
|
|
78
|
+
from 1
|
|
79
|
+
to 512
|
|
80
|
+
text collection_options[:width]
|
|
81
|
+
width 3
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
spinbox {
|
|
85
|
+
grid row: row, column: 4
|
|
86
|
+
from 1
|
|
87
|
+
to 512
|
|
88
|
+
text collection_options[:height]
|
|
89
|
+
width 3
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
spinbox {
|
|
93
|
+
grid row: row, column: 5
|
|
94
|
+
from 1
|
|
95
|
+
to 72
|
|
96
|
+
text collection_options[:default_zoom]
|
|
97
|
+
width 3
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
button {
|
|
101
|
+
grid row: row, column: 6
|
|
102
|
+
text 'X'
|
|
103
|
+
width 1
|
|
104
|
+
}
|
|
105
|
+
button {
|
|
106
|
+
grid row: row, column: 7
|
|
107
|
+
text '^'
|
|
108
|
+
width 1
|
|
109
|
+
}
|
|
110
|
+
button {
|
|
111
|
+
grid row: row, column: 8
|
|
112
|
+
text 'v'
|
|
113
|
+
width 1
|
|
114
|
+
}
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
row = image.collections_map.keys.size + 1
|
|
118
|
+
|
|
119
|
+
checkbutton {
|
|
120
|
+
grid row: row, column: 0
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
entry {
|
|
125
|
+
grid row: row, column: 1
|
|
126
|
+
text ''
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
entry {
|
|
130
|
+
grid row: row, column: 2
|
|
131
|
+
text ''
|
|
132
|
+
width 82
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
spinbox {
|
|
136
|
+
grid row: row, column: 3
|
|
137
|
+
from 1
|
|
138
|
+
to 512
|
|
139
|
+
text '24'
|
|
140
|
+
width 3
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
spinbox {
|
|
144
|
+
grid row: row, column: 4
|
|
145
|
+
from 1
|
|
146
|
+
to 512
|
|
147
|
+
text '24'
|
|
148
|
+
width 3
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
spinbox {
|
|
152
|
+
grid row: row, column: 5
|
|
153
|
+
from 1
|
|
154
|
+
to 72
|
|
155
|
+
text '12'
|
|
156
|
+
width 3
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
frame {
|
|
161
|
+
button {
|
|
162
|
+
text 'Reset'
|
|
163
|
+
|
|
164
|
+
on('command') do
|
|
165
|
+
image.initialize_collections_map(reset: true)
|
|
166
|
+
# TODO cause an update to all collections
|
|
167
|
+
end
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
class CryptopunksGui
|
|
2
|
+
module View
|
|
3
|
+
module StyleOptionsFrame
|
|
4
|
+
def led_style_options_frame(image: )
|
|
5
|
+
frame {
|
|
6
|
+
padding 0
|
|
7
|
+
|
|
8
|
+
label {
|
|
9
|
+
grid row: 0, column: 0, column_weight: 0
|
|
10
|
+
text 'Spacing:'
|
|
11
|
+
}
|
|
12
|
+
spinbox {
|
|
13
|
+
grid row: 0, column: 1
|
|
14
|
+
from 1
|
|
15
|
+
to 72
|
|
16
|
+
text <=> [image, :led_spacing]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
checkbutton {
|
|
20
|
+
grid row: 0, column: 2
|
|
21
|
+
variable <=> [image, :led_round_corner]
|
|
22
|
+
}
|
|
23
|
+
label {
|
|
24
|
+
grid row: 0, column: 3
|
|
25
|
+
text 'Round Corner'
|
|
26
|
+
|
|
27
|
+
on('Button-1') do
|
|
28
|
+
image.led_round_corner = !image.led_round_corner
|
|
29
|
+
end
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def sketch_style_options_frame(image: )
|
|
35
|
+
frame {
|
|
36
|
+
padding 0
|
|
37
|
+
|
|
38
|
+
label {
|
|
39
|
+
grid row: 0, column: 0, column_weight: 0
|
|
40
|
+
text 'Line:'
|
|
41
|
+
}
|
|
42
|
+
spinbox {
|
|
43
|
+
grid row: 0, column: 1
|
|
44
|
+
from 1
|
|
45
|
+
to 72
|
|
46
|
+
text <=> [image, :sketch_line]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def no_style_options_frame
|
|
52
|
+
frame { # filler
|
|
53
|
+
padding 0
|
|
54
|
+
height 0
|
|
55
|
+
width 0
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
data/cryptopunks-gui.gemspec
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: cryptopunks-gui 0.0.
|
|
5
|
+
# stub: cryptopunks-gui 0.0.15 ruby app
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "cryptopunks-gui".freeze
|
|
9
|
-
s.version = "0.0.
|
|
9
|
+
s.version = "0.0.15"
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["app".freeze]
|
|
13
|
-
s.authors = ["Andy Maleh".freeze]
|
|
14
|
-
s.date = "2021-
|
|
13
|
+
s.authors = ["Andy Maleh".freeze, "Gerald Bauer".freeze]
|
|
14
|
+
s.date = "2021-12-05"
|
|
15
15
|
s.description = "CryptoPunks GUI for Simplified Minting - Built with Glimmer DSL for Tk (requires ActiveTcl to run cryptopunks-gui command)".freeze
|
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
|
17
17
|
s.executables = ["cryptopunks-gui".freeze]
|
|
@@ -26,15 +26,21 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
"README.md",
|
|
27
27
|
"VERSION",
|
|
28
28
|
"app/cryptopunks_gui.rb",
|
|
29
|
+
"app/model/image.rb",
|
|
30
|
+
"app/view/help_dialog.rb",
|
|
31
|
+
"app/view/image_frame.rb",
|
|
32
|
+
"app/view/menu_bar.rb",
|
|
33
|
+
"app/view/preferences_dialog.rb",
|
|
34
|
+
"app/view/style_options_frame.rb",
|
|
29
35
|
"bin/cryptopunks-gui",
|
|
30
36
|
"cryptopunks-gui.gemspec",
|
|
31
37
|
"icons/cryptopunks-gui.icns",
|
|
32
38
|
"icons/cryptopunks-gui.png"
|
|
33
39
|
]
|
|
34
|
-
s.homepage = "http://github.com/
|
|
40
|
+
s.homepage = "http://github.com/cryptopunksnotdead/cryptopunks-gui".freeze
|
|
35
41
|
s.licenses = ["MIT".freeze]
|
|
36
42
|
s.post_install_message = "To launch CryptoPunks GUI, run command: cryptopunks-gui".freeze
|
|
37
|
-
s.rubygems_version = "3.
|
|
43
|
+
s.rubygems_version = "3.1.4".freeze
|
|
38
44
|
s.summary = "CryptoPunks GUI for Simplified Minting".freeze
|
|
39
45
|
|
|
40
46
|
if s.respond_to? :specification_version then
|
|
@@ -42,7 +48,7 @@ Gem::Specification.new do |s|
|
|
|
42
48
|
end
|
|
43
49
|
|
|
44
50
|
if s.respond_to? :add_runtime_dependency then
|
|
45
|
-
s.add_runtime_dependency(%q<glimmer-dsl-tk>.freeze, ["
|
|
51
|
+
s.add_runtime_dependency(%q<glimmer-dsl-tk>.freeze, ["= 0.0.49"])
|
|
46
52
|
s.add_runtime_dependency(%q<cryptopunks>.freeze, ["~> 2.0.1"])
|
|
47
53
|
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
48
54
|
s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
|
@@ -50,7 +56,7 @@ Gem::Specification.new do |s|
|
|
|
50
56
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
|
|
51
57
|
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
|
|
52
58
|
else
|
|
53
|
-
s.add_dependency(%q<glimmer-dsl-tk>.freeze, ["
|
|
59
|
+
s.add_dependency(%q<glimmer-dsl-tk>.freeze, ["= 0.0.49"])
|
|
54
60
|
s.add_dependency(%q<cryptopunks>.freeze, ["~> 2.0.1"])
|
|
55
61
|
s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
56
62
|
s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
metadata
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cryptopunks-gui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andy Maleh
|
|
8
|
+
- Gerald Bauer
|
|
8
9
|
autorequire:
|
|
9
10
|
bindir: bin
|
|
10
11
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
12
|
+
date: 2021-12-05 00:00:00.000000000 Z
|
|
12
13
|
dependencies:
|
|
13
14
|
- !ruby/object:Gem::Dependency
|
|
14
15
|
name: glimmer-dsl-tk
|
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
|
16
17
|
requirements:
|
|
17
|
-
- -
|
|
18
|
+
- - '='
|
|
18
19
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.0.
|
|
20
|
+
version: 0.0.49
|
|
20
21
|
type: :runtime
|
|
21
22
|
prerelease: false
|
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
24
|
requirements:
|
|
24
|
-
- -
|
|
25
|
+
- - '='
|
|
25
26
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.0.
|
|
27
|
+
version: 0.0.49
|
|
27
28
|
- !ruby/object:Gem::Dependency
|
|
28
29
|
name: cryptopunks
|
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -124,11 +125,17 @@ files:
|
|
|
124
125
|
- README.md
|
|
125
126
|
- VERSION
|
|
126
127
|
- app/cryptopunks_gui.rb
|
|
128
|
+
- app/model/image.rb
|
|
129
|
+
- app/view/help_dialog.rb
|
|
130
|
+
- app/view/image_frame.rb
|
|
131
|
+
- app/view/menu_bar.rb
|
|
132
|
+
- app/view/preferences_dialog.rb
|
|
133
|
+
- app/view/style_options_frame.rb
|
|
127
134
|
- bin/cryptopunks-gui
|
|
128
135
|
- cryptopunks-gui.gemspec
|
|
129
136
|
- icons/cryptopunks-gui.icns
|
|
130
137
|
- icons/cryptopunks-gui.png
|
|
131
|
-
homepage: http://github.com/
|
|
138
|
+
homepage: http://github.com/cryptopunksnotdead/cryptopunks-gui
|
|
132
139
|
licenses:
|
|
133
140
|
- MIT
|
|
134
141
|
metadata: {}
|
|
@@ -147,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
147
154
|
- !ruby/object:Gem::Version
|
|
148
155
|
version: '0'
|
|
149
156
|
requirements: []
|
|
150
|
-
rubygems_version: 3.
|
|
157
|
+
rubygems_version: 3.1.4
|
|
151
158
|
signing_key:
|
|
152
159
|
specification_version: 4
|
|
153
160
|
summary: CryptoPunks GUI for Simplified Minting
|