cryptopunks-gui 0.0.9 → 0.0.13
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 +24 -9
- data/VERSION +1 -1
- data/app/cryptopunks_gui.rb +17 -316
- 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 +13 -6
- data/icons/cryptopunks-gui.icns +0 -0
- metadata +14 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46ac37666e9b977617717e77af92359aa2644dee38fb7173bb6908e821c543b3
|
|
4
|
+
data.tar.gz: b22e902d9f9f9850a7fb378ac06a410333e18d290160e584b1bfdc8dfaefddf2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c375eb8fd78107079fd7e48f24ee8d344cd80ee9400a57085c1675d96e04b5b2477318179398960dcac2d9e6dd800c2ff05668fc07c71dc5cc0146e8bd623c74
|
|
7
|
+
data.tar.gz: 3a411372e9b4ee1e28e5f9f16d0358c16defb1e0e5f6fbbb10bff2ef10a49cc794fd49321c9c8f518f7b35270f4a07ae4b7205001cc88ac9d4c98e4ec9fa7c10
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 0.0.13
|
|
4
|
+
|
|
5
|
+
- Support older Ruby versions down to 2.7.2 by fixing an issue with not having `#name` method on `Symbol`
|
|
6
|
+
|
|
7
|
+
## 0.0.12
|
|
8
|
+
|
|
9
|
+
- Upgrade to glimmer-dsl-tk 0.0.46
|
|
10
|
+
- File & Help Menus
|
|
11
|
+
- Update COLLECTIONS_YAML_URL to point to cryptopunksnotdead repository (recently moved there)
|
|
12
|
+
- Add 'Mirror', 'Flip', 'Led' and 'Sketch' details (e.g. spacing or line) to output file name (e.g. '...-mirror.png')
|
|
13
|
+
- 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)
|
|
14
|
+
- Fix written file name for downloaded sprites (was excluding .png before)
|
|
15
|
+
- Fix issue with @punk_directory mistakenly referenced after being removed through refactoring
|
|
16
|
+
|
|
17
|
+
## 0.0.11
|
|
18
|
+
|
|
19
|
+
- Support configuring default collections through a web hosted yaml file at: https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/cryptopunks-collections.yml
|
|
20
|
+
- New Green Punks, Clown Punks, and Bubble Gum Punks collections
|
|
21
|
+
|
|
22
|
+
## 0.0.10
|
|
23
|
+
|
|
24
|
+
- Fix issue with cryptopunks GUI erroring when cancelling selection of a new output location (or getting blocked by OS for security reasons)
|
|
25
|
+
|
|
3
26
|
## 0.0.9
|
|
4
27
|
|
|
5
|
-
- Added Halloween special collections: Scream, Jack 'O' Lantern, Joker, and
|
|
28
|
+
- Added Halloween special collections: Scream, Jack 'O' Lantern, Joker, and Frankenstein
|
|
6
29
|
|
|
7
30
|
## 0.0.8
|
|
8
31
|
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# <img src="https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/icons/cryptopunks-gui.png" height=85 /> CryptoPunks GUI 0.0.
|
|
1
|
+
# <img src="https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/icons/cryptopunks-gui.png" height=85 /> CryptoPunks GUI 0.0.13
|
|
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
|
|
|
@@ -14,18 +14,18 @@ Minted cryptopunks are stored at `~/cryptopunks/` by default ([output location c
|
|
|
14
14
|
|
|
15
15
|
- [Tcl/Tk (ActiveTcl)](https://tkdocs.com/tutorial/install.html)
|
|
16
16
|
- [RVM](https://rvm.io/) (unless you are on Windows)
|
|
17
|
-
- [Ruby 3.0.2 compiled with RVM for Tk](https://rvm.io/integration/tk#tk) (unless you are on Windows for which Tcl/Tk instructions include installation of Ruby)
|
|
17
|
+
- [Ruby 3.0.2 compiled with RVM for Tk](https://rvm.io/integration/tk#tk) (unless you are on Windows for which Tcl/Tk instructions include installation of Ruby [get v3.0.2])
|
|
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.13
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Afterwards, run app via:
|
|
@@ -73,7 +73,13 @@ ruby app/cryptopunks_gui.rb
|
|
|
73
73
|
|
|
74
74
|
Change collection to pick a different collection of images.
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+

|
|
77
|
+
|
|
78
|
+
Image collections are configured in [cryptopunks-collections.yml](/cryptopunks-collections.yml).
|
|
79
|
+
|
|
80
|
+
If you cloned the project locally, you may edit [cryptopunks-collections.yml](/cryptopunks-collections.yml) to add/remove collections.
|
|
81
|
+
|
|
82
|
+
There are 41 available collections (mostly from https://github.com/cryptopunksnotdead/awesome-24px):
|
|
77
83
|
- [Punks](https://raw.githubusercontent.com/larvalabs/cryptopunks/master/punks.png) 
|
|
78
84
|
- [Mohawks](https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/mohawks.png) 
|
|
79
85
|
- [Blondies](https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/blondies.png) 
|
|
@@ -81,6 +87,9 @@ There are currently 38 available collections (from https://github.com/cryptopunk
|
|
|
81
87
|
- [Apes](https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/apes.png) 
|
|
82
88
|
- [Aliens](https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/aliens.png) 
|
|
83
89
|
- [Golden Punks](https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/goldenpunks.png) 
|
|
90
|
+
- [Green Punks](https://i.redd.it/uwrsn2lrr3o71.png)
|
|
91
|
+
- [Clown Punks](https://i.redd.it/ut0kk25heex71.png)
|
|
92
|
+
- [Bubble Gum Punks](https://i.redd.it/hjddd1s8ydx71.png)
|
|
84
93
|
- [Halloween Punks](https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/halloweenpunks.png) 
|
|
85
94
|
- [Scream Punks](https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/halloween/i/screampunks%402x.png)
|
|
86
95
|
- [Jack 'O' Lantern Punks](https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/halloween/i/jackpunks%402x.png)
|
|
@@ -113,10 +122,16 @@ There are currently 38 available collections (from https://github.com/cryptopunk
|
|
|
113
122
|
- [Punk Rocks](https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/punkrocks.png) 
|
|
114
123
|
- [Tulips](https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/tulips.png) 
|
|
115
124
|
|
|
116
|
-

|
|
117
|
-
|
|
118
125
|

|
|
119
126
|
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+

|
|
130
|
+
|
|
131
|
+

|
|
132
|
+
|
|
133
|
+

|
|
134
|
+
|
|
120
135
|

|
|
121
136
|
|
|
122
137
|

|
|
@@ -221,7 +236,7 @@ You may select a new output location by clicking on the `...` button.
|
|
|
221
236
|
|
|
222
237
|
[MIT](LICENSE.txt)
|
|
223
238
|
|
|
224
|
-
Copyright (c) 2021 - Cryptopunks GUI by [
|
|
239
|
+
Copyright (c) 2021 - Cryptopunks GUI by [Crypto Punk's Not Dead](https://github.com/cryptopunksnotdead)
|
|
225
240
|
|
|
226
241
|
--
|
|
227
242
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.13
|
data/app/cryptopunks_gui.rb
CHANGED
|
@@ -1,341 +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
|
-
COLLECTION_URL_MAP = {
|
|
17
|
-
'Punks' => {url: 'https://raw.githubusercontent.com/larvalabs/cryptopunks/master/punks.png', width: 24, height: 24, default_zoom: 12},
|
|
18
|
-
'Mohawks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/mohawks.png', width: 24, height: 24, default_zoom: 12},
|
|
19
|
-
'Blondies' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/blondies.png', width: 24, height: 24, default_zoom: 12},
|
|
20
|
-
'Zombies' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/zombies.png', width: 24, height: 24, default_zoom: 12},
|
|
21
|
-
'Apes' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/apes.png', width: 24, height: 24, default_zoom: 12},
|
|
22
|
-
'Aliens' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/aliens.png', width: 24, height: 24, default_zoom: 12},
|
|
23
|
-
'Golden Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/goldenpunks.png', width: 24, height: 24, default_zoom: 12},
|
|
24
|
-
'Halloween Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/halloweenpunks.png', width: 24, height: 24, default_zoom: 12},
|
|
25
|
-
'Scream Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/halloween/i/screampunks%402x.png', width: 48, height: 48, default_zoom: 6},
|
|
26
|
-
"Jack 'O' Lantern Punks" => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/halloween/i/jackpunks%402x.png', width: 48, height: 48, default_zoom: 6},
|
|
27
|
-
'Joker Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/halloween/i/jokerpunks%402x.png', width: 48, height: 48, default_zoom: 6},
|
|
28
|
-
'Frankenstein Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/halloween/i/frankensteinpunks%402x.png', width: 48, height: 48, default_zoom: 6},
|
|
29
|
-
'Front Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/frontpunks.png', width: 24, height: 24, default_zoom: 12},
|
|
30
|
-
'More Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/morepunks.png', width: 24, height: 24, default_zoom: 12},
|
|
31
|
-
'Expansion Punks' => {url: 'https://expansionpunks.com/provenance/expansionpunks.png', width: 24, height: 24, default_zoom: 12},
|
|
32
|
-
'Avalanche Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/avalanchepunks.png', width: 24, height: 24, default_zoom: 12},
|
|
33
|
-
'International Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/intlpunks.png', width: 24, height: 24, default_zoom: 12},
|
|
34
|
-
'Ape Punks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/apepunks.png', width: 24, height: 24, default_zoom: 12},
|
|
35
|
-
'Alien Clan' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/alienclan.png', width: 24, height: 24, default_zoom: 12},
|
|
36
|
-
'Bored Apes' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/boredapes.png', width: 28, height: 28, default_zoom: 10},
|
|
37
|
-
'Bored Apes Blue' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/boredapes_blue.png', width: 28, height: 28, default_zoom: 10},
|
|
38
|
-
'Bored Apes Red' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/boredapes_red.png', width: 28, height: 28, default_zoom: 10},
|
|
39
|
-
'Bored Apes Neon Glow' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/boredapes_neon_glow.png', width: 28, height: 28, default_zoom: 10},
|
|
40
|
-
'Bored Apes Stars and Stripes' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/boredapes_stars_and_stripes.png', width: 28, height: 28, default_zoom: 10},
|
|
41
|
-
'Bored Apes Acid' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/boredapes_acid.png', width: 28, height: 28, default_zoom: 10},
|
|
42
|
-
'Cool Cats' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats.png', width: 24, height: 24, default_zoom: 12},
|
|
43
|
-
'Cool Cats Mohawks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_mohawks.png', width: 24, height: 24, default_zoom: 12},
|
|
44
|
-
'Cool Cats Ninjas' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_ninjas.png', width: 24, height: 24, default_zoom: 12},
|
|
45
|
-
'Cool Cats TV Heads' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_tvheads.png', width: 24, height: 24, default_zoom: 12},
|
|
46
|
-
'Cool Cats Pirates' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_pirates.png', width: 24, height: 24, default_zoom: 12},
|
|
47
|
-
'Cool Cats Unicorns' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_unicorns.png', width: 24, height: 24, default_zoom: 12},
|
|
48
|
-
'Cool Cats Dragons' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_dragons.png', width: 24, height: 24, default_zoom: 12},
|
|
49
|
-
'Cool Cats Frogs' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/coolcats_frogs.png', width: 24, height: 24, default_zoom: 12},
|
|
50
|
-
'Pudgy Penguins' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/pudgypenguins.png', width: 24, height: 24, default_zoom: 12},
|
|
51
|
-
'Dodge' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/dodge.png', width: 24, height: 24, default_zoom: 12},
|
|
52
|
-
'Rocks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/rocks.png', width: 24, height: 24, default_zoom: 12},
|
|
53
|
-
'Punk Rocks' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/programming-cryptopunks/master/i/punkrocks.png', width: 24, height: 24, default_zoom: 12},
|
|
54
|
-
'Tulips' => {url: 'https://raw.githubusercontent.com/cryptopunksnotdead/awesome-24px/master/collection/tulips.png', width: 24, height: 24, default_zoom: 12},
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
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
|
|
58
21
|
|
|
59
22
|
def initialize
|
|
60
|
-
|
|
61
|
-
initialize_collection
|
|
62
|
-
load_config
|
|
63
|
-
initialize_defaults
|
|
64
|
-
observe_image_attribute_changes
|
|
23
|
+
@image = Model::Image.new
|
|
65
24
|
create_gui
|
|
66
|
-
|
|
67
|
-
@root.open
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def collection_options
|
|
71
|
-
COLLECTION_URL_MAP.keys
|
|
25
|
+
@image.image_index = 0
|
|
72
26
|
end
|
|
73
27
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def style_options
|
|
79
|
-
STYLES
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def initialize_punk_directory
|
|
83
|
-
@punk_directory = @punk_config_directory = File.join(Dir.home, 'cryptopunks')
|
|
84
|
-
FileUtils.mkdir_p(@punk_directory)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def initialize_collection
|
|
88
|
-
return if @collection && @collection == @last_collection
|
|
89
|
-
@collection ||= COLLECTION_URL_MAP.keys.first
|
|
90
|
-
url = COLLECTION_URL_MAP[@collection][:url]
|
|
91
|
-
width = COLLECTION_URL_MAP[@collection][:width]
|
|
92
|
-
height = COLLECTION_URL_MAP[@collection][:height]
|
|
93
|
-
@punk_file = File.join(@punk_config_directory, File.basename(url, '.png'))
|
|
94
|
-
File.write(@punk_file, Net::HTTP.get(URI(url))) unless File.exist?(@punk_file)
|
|
95
|
-
@images ||= {}
|
|
96
|
-
@images[@collection] ||= Punks::Image::Composite.read(@punk_file, width: width, height: height)
|
|
97
|
-
@last_collection = @collection
|
|
98
|
-
self.image_index = 0
|
|
99
|
-
@image_index_spinbox.to = @images[@collection].size - 1 if @image_index_spinbox
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def load_config
|
|
103
|
-
@punk_config_file = File.join(@punk_config_directory, 'cryptopunks.yml')
|
|
104
|
-
FileUtils.touch(@punk_config_file)
|
|
105
|
-
@punk_config = YAML.load(File.read(@punk_config_file)) || {punk_directory: @punk_directory}
|
|
106
|
-
@punk_directory = @punk_config[:punk_directory]
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def save_config
|
|
110
|
-
File.write(@punk_config_file, YAML.dump(@punk_config))
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def initialize_defaults
|
|
114
|
-
@collection = COLLECTION_URL_MAP.keys.first
|
|
115
|
-
@zoom = 12
|
|
116
|
-
@palette = PALETTES.first
|
|
117
|
-
@style = STYLES.first
|
|
118
|
-
@led_spacing = 2
|
|
119
|
-
@led_round_corner = false
|
|
120
|
-
@sketch_line = 1
|
|
121
|
-
@mirror = false
|
|
122
|
-
@flip = false
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def observe_image_attribute_changes
|
|
126
|
-
observer = Glimmer::DataBinding::Observer.proc { generate_image }
|
|
127
|
-
observer.observe(self, :collection)
|
|
128
|
-
observer.observe(self, :image_index)
|
|
129
|
-
observer.observe(self, :zoom)
|
|
130
|
-
observer.observe(self, :palette)
|
|
131
|
-
observer.observe(self, :style)
|
|
132
|
-
observer.observe(self, :led_spacing)
|
|
133
|
-
observer.observe(self, :led_round_corner)
|
|
134
|
-
observer.observe(self, :sketch_line)
|
|
135
|
-
observer.observe(self, :mirror)
|
|
136
|
-
observer.observe(self, :flip)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def generate_image
|
|
140
|
-
initialize_collection
|
|
141
|
-
return if @image_index.to_i > @images[@collection].size
|
|
142
|
-
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")
|
|
143
|
-
puts "Writing punk image to #{image_location}"
|
|
144
|
-
selected_punk = @images[@collection][@image_index.to_i]
|
|
145
|
-
selected_punk = selected_punk.change_palette8bit(Palette8bit.const_get(@palette.gsub(' ', '_').upcase.to_sym)) if @palette != PALETTES.first
|
|
146
|
-
@original_zoom = @zoom
|
|
147
|
-
if @previous_collection && @collection != @previous_collection && COLLECTION_URL_MAP[@collection][:width] != COLLECTION_URL_MAP[@previous_collection][:width]
|
|
148
|
-
@zoom = COLLECTION_URL_MAP[@collection][:default_zoom]
|
|
149
|
-
end
|
|
150
|
-
if @style != STYLES.first
|
|
151
|
-
style_options = {}
|
|
152
|
-
if @style == 'Led'
|
|
153
|
-
style_options[:spacing] = @led_spacing.to_i
|
|
154
|
-
style_options[:round_corner] = @led_round_corner
|
|
155
|
-
end
|
|
156
|
-
if @style == 'Sketch'
|
|
157
|
-
style_options[:line] = @sketch_line.to_i
|
|
158
|
-
end
|
|
159
|
-
selected_punk = selected_punk.send(@style.underscore, @zoom.to_i, **style_options)
|
|
160
|
-
end
|
|
161
|
-
selected_punk = selected_punk.mirror if @mirror
|
|
162
|
-
selected_punk = selected_punk.flip if @flip
|
|
163
|
-
selected_punk = selected_punk.zoom(@zoom.to_i) if @style == STYLES.first
|
|
164
|
-
selected_punk.save(image_location)
|
|
165
|
-
@image_label.image = image_location
|
|
166
|
-
@output_location_entry.text = image_location
|
|
167
|
-
@previous_style = @style
|
|
168
|
-
@previous_collection = @collection
|
|
169
|
-
notify_observers(:zoom) if @zoom != @original_zoom
|
|
28
|
+
def launch
|
|
29
|
+
@root.open
|
|
170
30
|
end
|
|
171
31
|
|
|
172
32
|
def create_gui
|
|
173
|
-
@root = root {
|
|
33
|
+
@root = root { |root_proxy|
|
|
174
34
|
title 'CryptoPunks GUI'
|
|
175
35
|
iconphoto File.expand_path('../icons/cryptopunks-gui.png', __dir__)
|
|
176
36
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
combobox {
|
|
182
|
-
readonly true
|
|
183
|
-
text <=> [self, :collection]
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
label {
|
|
187
|
-
text 'Image Index:'
|
|
188
|
-
}
|
|
189
|
-
@image_index_spinbox = spinbox {
|
|
190
|
-
from 0
|
|
191
|
-
to @images[@collection].size - 1
|
|
192
|
-
text <=> [self, :image_index]
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
label {
|
|
196
|
-
text 'Zoom:'
|
|
197
|
-
}
|
|
198
|
-
spinbox {
|
|
199
|
-
from 1
|
|
200
|
-
to 72
|
|
201
|
-
text <=> [self, :zoom]
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
label {
|
|
205
|
-
text 'Palette:'
|
|
206
|
-
}
|
|
207
|
-
combobox {
|
|
208
|
-
readonly true
|
|
209
|
-
text <=> [self, :palette]
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
label {
|
|
213
|
-
text 'Style:'
|
|
214
|
-
}
|
|
215
|
-
combobox {
|
|
216
|
-
readonly true
|
|
217
|
-
text <=> [self, :style, after_write: ->(val) {add_style_options}]
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
@style_options_frame = frame {
|
|
221
|
-
padding 0
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
frame {
|
|
225
|
-
padding 0
|
|
226
|
-
|
|
227
|
-
checkbutton {
|
|
228
|
-
grid row: 0, column: 0, column_weight: 0
|
|
229
|
-
variable <=> [self, :mirror]
|
|
230
|
-
}
|
|
231
|
-
label {
|
|
232
|
-
grid row: 0, column: 1
|
|
233
|
-
text 'Mirror'
|
|
234
|
-
|
|
235
|
-
on('Button-1') do
|
|
236
|
-
self.mirror = !mirror
|
|
237
|
-
end
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
checkbutton {
|
|
241
|
-
grid row: 0, column: 2
|
|
242
|
-
variable <=> [self, :flip]
|
|
243
|
-
}
|
|
244
|
-
label {
|
|
245
|
-
grid row: 0, column: 3
|
|
246
|
-
text 'Flip'
|
|
247
|
-
|
|
248
|
-
on('Button-1') do
|
|
249
|
-
self.flip = !flip
|
|
250
|
-
end
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
label {
|
|
255
|
-
text 'Output Location:'
|
|
256
|
-
}
|
|
257
|
-
frame {
|
|
258
|
-
padding 0
|
|
259
|
-
|
|
260
|
-
@output_location_entry = entry {
|
|
261
|
-
grid row: 0, column: 0
|
|
262
|
-
readonly true
|
|
263
|
-
width 47
|
|
264
|
-
}
|
|
265
|
-
button {
|
|
266
|
-
grid row: 0, column: 1
|
|
267
|
-
text '...'
|
|
268
|
-
width 1.1
|
|
269
|
-
|
|
270
|
-
on('command') do
|
|
271
|
-
@punk_directory = choose_directory(parent: @root)
|
|
272
|
-
@punk_config[:punk_directory] = @punk_directory
|
|
273
|
-
save_config
|
|
274
|
-
generate_image
|
|
275
|
-
end
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
@image_label = label {
|
|
280
|
-
grid row_weight: 1
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
def add_style_options
|
|
287
|
-
@style_options_frame.content {
|
|
288
|
-
@style_options_frame.children.each(&:destroy)
|
|
289
|
-
if @style == 'Led'
|
|
290
|
-
frame {
|
|
291
|
-
padding 0
|
|
292
|
-
|
|
293
|
-
label {
|
|
294
|
-
grid row: 0, column: 0, column_weight: 0
|
|
295
|
-
text 'Spacing:'
|
|
296
|
-
}
|
|
297
|
-
spinbox {
|
|
298
|
-
grid row: 0, column: 1
|
|
299
|
-
from 1
|
|
300
|
-
to 72
|
|
301
|
-
text <=> [self, :led_spacing]
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
checkbutton {
|
|
305
|
-
grid row: 0, column: 2
|
|
306
|
-
variable <=> [self, :led_round_corner]
|
|
307
|
-
}
|
|
308
|
-
label {
|
|
309
|
-
grid row: 0, column: 3
|
|
310
|
-
text 'Round Corner'
|
|
311
|
-
|
|
312
|
-
on('Button-1') do
|
|
313
|
-
self.led_round_corner = !led_round_corner
|
|
314
|
-
end
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
elsif @style == 'Sketch'
|
|
318
|
-
frame {
|
|
319
|
-
padding 0
|
|
320
|
-
|
|
321
|
-
label {
|
|
322
|
-
grid row: 0, column: 0, column_weight: 0
|
|
323
|
-
text 'Line:'
|
|
324
|
-
}
|
|
325
|
-
spinbox {
|
|
326
|
-
grid row: 0, column: 1
|
|
327
|
-
from 1
|
|
328
|
-
to 72
|
|
329
|
-
text <=> [self, :sketch_line]
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
else
|
|
333
|
-
frame { # filler
|
|
334
|
-
padding 0
|
|
335
|
-
height 0
|
|
336
|
-
width 0
|
|
337
|
-
}
|
|
338
|
-
end
|
|
37
|
+
cryptopunks_gui_menu_bar(root: root_proxy, image: @image)
|
|
38
|
+
|
|
39
|
+
image_frame(root: root_proxy, image: @image)
|
|
339
40
|
}
|
|
340
41
|
end
|
|
341
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.write(@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, :images)
|
|
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 {
|
|
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.13 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.13"
|
|
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
13
|
s.authors = ["Andy Maleh".freeze]
|
|
14
|
-
s.date = "2021-
|
|
14
|
+
s.date = "2021-11-24"
|
|
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,14 +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",
|
|
37
|
+
"icons/cryptopunks-gui.icns",
|
|
31
38
|
"icons/cryptopunks-gui.png"
|
|
32
39
|
]
|
|
33
40
|
s.homepage = "http://github.com/AndyObtiva/cryptopunks-gui".freeze
|
|
34
41
|
s.licenses = ["MIT".freeze]
|
|
35
42
|
s.post_install_message = "To launch CryptoPunks GUI, run command: cryptopunks-gui".freeze
|
|
36
|
-
s.rubygems_version = "3.
|
|
43
|
+
s.rubygems_version = "3.1.4".freeze
|
|
37
44
|
s.summary = "CryptoPunks GUI for Simplified Minting".freeze
|
|
38
45
|
|
|
39
46
|
if s.respond_to? :specification_version then
|
|
@@ -41,7 +48,7 @@ Gem::Specification.new do |s|
|
|
|
41
48
|
end
|
|
42
49
|
|
|
43
50
|
if s.respond_to? :add_runtime_dependency then
|
|
44
|
-
s.add_runtime_dependency(%q<glimmer-dsl-tk>.freeze, ["
|
|
51
|
+
s.add_runtime_dependency(%q<glimmer-dsl-tk>.freeze, ["= 0.0.47"])
|
|
45
52
|
s.add_runtime_dependency(%q<cryptopunks>.freeze, ["~> 2.0.1"])
|
|
46
53
|
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
47
54
|
s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
|
@@ -49,7 +56,7 @@ Gem::Specification.new do |s|
|
|
|
49
56
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
|
|
50
57
|
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
|
|
51
58
|
else
|
|
52
|
-
s.add_dependency(%q<glimmer-dsl-tk>.freeze, ["
|
|
59
|
+
s.add_dependency(%q<glimmer-dsl-tk>.freeze, ["= 0.0.47"])
|
|
53
60
|
s.add_dependency(%q<cryptopunks>.freeze, ["~> 2.0.1"])
|
|
54
61
|
s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
55
62
|
s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
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.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andy Maleh
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-11-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: glimmer-dsl-tk
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - '='
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.0.
|
|
19
|
+
version: 0.0.47
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - '='
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.0.
|
|
26
|
+
version: 0.0.47
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: cryptopunks
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -124,8 +124,15 @@ files:
|
|
|
124
124
|
- README.md
|
|
125
125
|
- VERSION
|
|
126
126
|
- app/cryptopunks_gui.rb
|
|
127
|
+
- app/model/image.rb
|
|
128
|
+
- app/view/help_dialog.rb
|
|
129
|
+
- app/view/image_frame.rb
|
|
130
|
+
- app/view/menu_bar.rb
|
|
131
|
+
- app/view/preferences_dialog.rb
|
|
132
|
+
- app/view/style_options_frame.rb
|
|
127
133
|
- bin/cryptopunks-gui
|
|
128
134
|
- cryptopunks-gui.gemspec
|
|
135
|
+
- icons/cryptopunks-gui.icns
|
|
129
136
|
- icons/cryptopunks-gui.png
|
|
130
137
|
homepage: http://github.com/AndyObtiva/cryptopunks-gui
|
|
131
138
|
licenses:
|
|
@@ -146,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
146
153
|
- !ruby/object:Gem::Version
|
|
147
154
|
version: '0'
|
|
148
155
|
requirements: []
|
|
149
|
-
rubygems_version: 3.
|
|
156
|
+
rubygems_version: 3.1.4
|
|
150
157
|
signing_key:
|
|
151
158
|
specification_version: 4
|
|
152
159
|
summary: CryptoPunks GUI for Simplified Minting
|