lib/glimmer/rake_task/scaffold.rb
# Copyright (c) 2021-2024 Andy Maleh
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
require 'fileutils'
require 'os'
require 'facets/string/titlecase'
# TODO refactor to nest under RakeTask namespace
MAIN_OBJECT = self
module Glimmer
module RakeTask
class Scaffold
class << self
include FileUtils
VERSION = File.read(File.expand_path('../../../../VERSION', __FILE__)).strip
RUBY_VERSION = File.read(File.expand_path('../../../../RUBY_VERSION', __FILE__)).strip
# TODO externalize all constants into scaffold/files
GITIGNORE = <<~MULTI_LINE_STRING
*.gem
*.rbc
/.config
/.mvn/
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
# Used by dotenv library to load environment variables.
# .env
## Specific to RubyMotion:
.dat*
.repl_history
build/
*.bridgesupport
build-iPhoneOS/
build-iPhoneSimulator/
## Specific to RubyMotion (use of CocoaPods):
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# vendor/Pods/
## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/
## Environment normalization:
/.bundle/
/vendor/bundle
/lib/bundler/man/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
# Mac
.DS_Store
# Gladiator (Glimmer Editor)
.gladiator
.gladiator-scratchpad
# Glimmer
/dist/
/packages/
MULTI_LINE_STRING
GEMFILE_PREFIX = <<~MULTI_LINE_STRING
# frozen_string_literal: true
source 'https://rubygems.org'
git_source(:github) {|repo_name| "https://github.com/\#{repo_name}" }
MULTI_LINE_STRING
GEMFILE_APP_MIDFIX = <<~MULTI_LINE_STRING
gem 'glimmer-dsl-libui', '~> #{VERSION}'
MULTI_LINE_STRING
GEMFILE_GEM_MIDFIX = <<~MULTI_LINE_STRING
gem 'glimmer-dsl-libui', '~> #{VERSION.split('.')[0...2].join('.')}'
MULTI_LINE_STRING
GEMFILE_SUFFIX = <<~MULTI_LINE_STRING
group :development do
gem 'rspec', '~> 3.5.0'
gem 'juwelier', '2.4.9'
gem 'simplecov', '>= 0'
end
MULTI_LINE_STRING
APP_GEMFILE = GEMFILE_PREFIX + GEMFILE_APP_MIDFIX + GEMFILE_SUFFIX
GEM_GEMFILE = GEMFILE_PREFIX + GEMFILE_GEM_MIDFIX + GEMFILE_SUFFIX
def app(app_name)
common_app(app_name)
end
def common_app(app_name, window_type = :app, window_options = {})
gem_name = file_name(app_name)
gem_summary = human_name(app_name)
return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
# system "ruby -S gem install bundler --no-document" if OS.windows? # resolves freezing issue with warbler and bundler 2.2.29 included in JRuby
system "ruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exist?
system "ruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? || `git config --get user.name`.strip.empty?
cd gem_name
rm_rf 'lib'
write '.gitignore', GITIGNORE
write '.ruby-version', RUBY_VERSION
write '.ruby-gemset', app_name
write 'VERSION', '1.0.0'
write 'LICENSE.txt', "Copyright (c) #{Time.now.year} #{app_name}"
write 'Gemfile', gemfile(window_type)
write 'Rakefile', gem_rakefile(app_name, nil, gem_name)
mkdir 'app'
write "app/#{file_name(app_name)}.rb", app_main_file(app_name)
mkdir_p "app/#{file_name(app_name)}/model"
mkdir_p "app/#{file_name(app_name)}/view"
custom_window(class_name(app_name), current_dir_name, window_type, custom_window_class_name: 'Application')
app_model(current_dir_name)
mkdir_p 'icons/windows'
icon_file = "icons/windows/#{human_name(app_name)}.ico"
cp File.expand_path('../../../../icons/scaffold_app.ico', __FILE__), icon_file
puts "Created #{current_dir_name}/#{icon_file}"
mkdir_p 'icons/macosx'
icon_file = "icons/macosx/#{human_name(app_name)}.icns"
cp File.expand_path('../../../../icons/scaffold_app.icns', __FILE__), icon_file
puts "Created #{current_dir_name}/#{icon_file}"
mkdir_p 'icons/linux'
icon_file = "icons/linux/#{human_name(app_name)}.png"
cp File.expand_path('../../../../icons/scaffold_app.png', __FILE__), icon_file
puts "Created #{current_dir_name}/#{icon_file}"
mkdir_p "app/#{file_name(app_name)}"
write "app/#{file_name(app_name)}/launch.rb", app_launch_file(app_name)
mkdir_p 'bin'
write "bin/#{file_name(app_name)}", app_bin_command_file(app_name)
FileUtils.chmod 0755, "bin/#{file_name(app_name)}"
if OS.windows?
system "bundle"
system "rspec --init"
else
system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
end
write 'spec/spec_helper.rb', spec_helper_file
if OS.mac? || OS.linux?
system "bash -c '#{RVM_FUNCTION}\n cd .\n glimmer run\n'"
else
system "glimmer run"
end
end
def custom_window(custom_window_name, namespace, window_type = nil, window_options = {})
namespace ||= current_dir_name
root_dir = File.exist?('app') ? 'app' : 'lib'
parent_dir = "#{root_dir}/#{file_name(namespace)}/view"
return puts("The file '#{parent_dir}/#{file_name(custom_window_name)}.rb' already exists. Please either remove or pick a different name.") if File.exist?("#{parent_dir}/#{file_name(custom_window_name)}.rb")
mkdir_p parent_dir unless File.exist?(parent_dir)
write "#{parent_dir}/#{file_name(custom_window_name)}.rb", custom_window_file(custom_window_name, namespace, window_type, window_options)
end
def custom_control(custom_control_name, namespace)
namespace ||= current_dir_name
root_dir = File.exist?('app') ? 'app' : 'lib'
parent_dir = "#{root_dir}/#{file_name(namespace)}/view"
return puts("The file '#{parent_dir}/#{file_name(custom_control_name)}.rb' already exists. Please either remove or pick a different name.") if File.exist?("#{parent_dir}/#{file_name(custom_control_name)}.rb")
mkdir_p parent_dir unless File.exist?(parent_dir)
write "#{parent_dir}/#{file_name(custom_control_name)}.rb", custom_control_file(custom_control_name, namespace)
end
def custom_shape(custom_shape_name, namespace)
namespace ||= current_dir_name
root_dir = File.exist?('app') ? 'app' : 'lib'
parent_dir = "#{root_dir}/#{file_name(namespace)}/view"
return puts("The file '#{parent_dir}/#{file_name(custom_shape_name)}.rb' already exists. Please either remove or pick a different name.") if File.exist?("#{parent_dir}/#{file_name(custom_shape_name)}.rb")
mkdir_p parent_dir unless File.exist?(parent_dir)
write "#{parent_dir}/#{file_name(custom_shape_name)}.rb", custom_shape_file(custom_shape_name, namespace)
end
def custom_window_gem(custom_window_name, namespace)
gem_name = "glimmer-libui-cw-#{custom_window_name.underscore}"
gem_summary = "#{human_name(custom_window_name)} - Glimmer Custom Window"
begin
custom_window_keyword = dsl_control_name(custom_window_name)
MAIN_OBJECT.method(custom_window_keyword)
return puts("CustomWindow keyword `#{custom_window_keyword}` is unavailable (occupied by a built-in Ruby method)! Please pick a different name.")
rescue NameError
# No Op (keyword is not taken by a built in Ruby method)
end
if namespace
gem_name += "-#{namespace.underscore}"
gem_summary += " (#{human_name(namespace)})"
else
return puts('Namespace is required! Usage: glimmer scaffold:gem:customwindow[name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
namespace = 'glimmer'
end
return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
# system "ruby -S gem install bundler --no-document" if OS.windows? # resolves freezing issue with warbler and bundler 2.2.29 included in JRuby
system "ruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exist?
system "ruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? && `git config --get user.name`.strip.empty?
cd gem_name
write '.gitignore', GITIGNORE
write '.ruby-version', RUBY_VERSION
write '.ruby-gemset', gem_name
write 'VERSION', '1.0.0'
write 'Gemfile', GEM_GEMFILE
write 'Rakefile', gem_rakefile(custom_window_name, namespace, gem_name)
append "lib/#{gem_name}.rb", gem_main_file(custom_window_name, namespace)
custom_window(custom_window_name, namespace, :gem)
app_model(current_dir_name, namespace)
mkdir_p "lib/#{gem_name}"
write "lib/#{gem_name}/launch.rb", gem_launch_file(gem_name, custom_window_name, namespace)
mkdir_p 'bin'
write "bin/#{file_name(custom_window_name)}", app_bin_command_file(gem_name, custom_window_name, namespace)
FileUtils.chmod 0755, "bin/#{file_name(custom_window_name)}"
if OS.windows?
system "bundle"
system "rspec --init"
else
system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
end
write 'spec/spec_helper.rb', spec_helper_file
mkdir_p 'icons/windows'
icon_file = "icons/windows/#{human_name(gem_name)}.ico"
cp File.expand_path('../../../../icons/scaffold_app.ico', __FILE__), icon_file
puts "Created #{current_dir_name}/#{icon_file}"
mkdir_p 'icons/macosx'
icon_file = "icons/macosx/#{human_name(gem_name)}.icns"
cp File.expand_path('../../../../icons/scaffold_app.icns', __FILE__), icon_file
puts "Created #{current_dir_name}/#{icon_file}"
mkdir_p 'icons/linux'
icon_file = "icons/linux/#{human_name(gem_name)}.png"
cp File.expand_path('../../../../icons/scaffold_app.png', __FILE__), icon_file
puts "Created #{current_dir_name}/#{icon_file}"
if OS.mac? || OS.linux?
system "bash -c '#{RVM_FUNCTION}\n cd .\n glimmer run\n'"
else
system "glimmer run"
end
puts "Finished creating #{gem_name} Ruby gem."
puts 'Edit Rakefile to configure gem details.'
puts 'Run `rake` to execute specs.'
puts 'Run `rake build` to build gem.'
puts 'Run `rake release` to release into rubygems.org once ready.'
end
def custom_control_gem(custom_control_name, namespace)
gem_name = "glimmer-libui-cc-#{custom_control_name.underscore}"
gem_summary = "#{human_name(custom_control_name)} - Glimmer Custom Control"
if namespace
gem_name += "-#{namespace.underscore}"
gem_summary += " (#{human_name(namespace)})"
else
return puts('Namespace is required! Usage: glimmer scaffold:custom_control_gem[custom_control_name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
namespace = 'glimmer'
end
return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
# system "ruby -S gem install bundler --no-document" if OS.windows? # resolves freezing issue with warbler and bundler 2.2.29 included in JRuby
system "ruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exist?
system "ruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? && `git config --get user.name`.strip.empty?
cd gem_name
write '.gitignore', GITIGNORE
write '.ruby-version', RUBY_VERSION
write '.ruby-gemset', gem_name
write 'VERSION', '1.0.0'
write 'Gemfile', GEM_GEMFILE
write 'Rakefile', gem_rakefile
append "lib/#{gem_name}.rb", gem_main_file(custom_control_name, namespace)
custom_control(custom_control_name, namespace)
if OS.windows?
system "bundle"
system "rspec --init"
else
system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
end
write 'spec/spec_helper.rb', spec_helper_file
puts "Finished creating #{gem_name} Ruby gem."
puts 'Edit Rakefile to configure gem details.'
puts 'Run `rake` to execute specs.'
puts 'Run `rake build` to build gem.'
puts 'Run `rake release` to release into rubygems.org once ready.'
end
def custom_shape_gem(custom_shape_name, namespace)
gem_name = "glimmer-libui-cs-#{custom_shape_name.underscore}"
gem_summary = "#{human_name(custom_shape_name)} - Glimmer Custom Shape"
if namespace
gem_name += "-#{namespace.underscore}"
gem_summary += " (#{human_name(namespace)})"
else
return puts('Namespace is required! Usage: glimmer scaffold:custom_shape_gem[custom_shape_name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
namespace = 'glimmer'
end
return puts("The directory '#{gem_name}' already exists. Please either remove or pick a different name.") if Dir.exist?(gem_name)
# system "ruby -S gem install bundler --no-document" if OS.windows? # resolves freezing issue with warbler and bundler 2.2.29 included in JRuby
system "ruby -S gem install juwelier -v2.4.9 --no-document" unless juwelier_exist?
system "ruby -S juwelier --markdown --rspec --summary '#{gem_summary}' --description '#{gem_summary}' #{gem_name}"
return puts('Your Git user.name and/or github.user are missing! Please add in for Juwelier to help Glimmer with Scaffolding.') if `git config --get github.user`.strip.empty? && `git config --get user.name`.strip.empty?
cd gem_name
write '.gitignore', GITIGNORE
write '.ruby-version', RUBY_VERSION
write '.ruby-gemset', gem_name
write 'VERSION', '1.0.0'
write 'Gemfile', GEM_GEMFILE
write 'Rakefile', gem_rakefile
append "lib/#{gem_name}.rb", gem_main_file(custom_shape_name, namespace)
custom_shape(custom_shape_name, namespace)
if OS.windows?
system "bundle"
system "rspec --init"
else
system "bash -c '#{RVM_FUNCTION}\n cd .\n bundle\n rspec --init\n'"
end
write 'spec/spec_helper.rb', spec_helper_file
puts "Finished creating #{gem_name} Ruby gem."
puts 'Edit Rakefile to configure gem details.'
puts 'Run `rake` to execute specs.'
puts 'Run `rake build` to build gem.'
puts 'Run `rake release` to release into rubygems.org once ready.'
end
def app_model(current_dir_name, namespace = nil)
model_name = 'Greeting'
namespace ||= current_dir_name
root_dir = File.exist?('app') ? 'app' : 'lib'
parent_dir = "#{root_dir}/#{file_name(namespace)}/model"
return puts("The file '#{parent_dir}/#{file_name(model_name)}.rb' already exists. Please either remove or pick a different name.") if File.exist?("#{parent_dir}/#{file_name(model_name)}.rb")
mkdir_p parent_dir unless File.exist?(parent_dir)
write "#{parent_dir}/#{file_name(model_name)}.rb", model_file(model_name, namespace)
end
private
def juwelier_exist?
OS.windows? ? system('where juwelier') : system('which juwelier')
end
def write(file, content)
File.write file, content
file_path = File.expand_path(file)
puts "Created #{current_dir_name}/#{file}"
end
def append(file, content)
File.open(file, 'a') do |f|
f.write(content)
end
end
def current_dir_name
File.basename(File.expand_path('.'))
end
def class_name(app_name)
app_name.underscore.camelcase(:upper)
end
def file_name(app_name)
app_name.underscore
end
alias dsl_control_name file_name
def human_name(app_name)
app_name.underscore.titlecase
end
def gemfile(window_type)
APP_GEMFILE
end
def app_main_file(app_name)
<<~MULTI_LINE_STRING
$LOAD_PATH.unshift(File.expand_path('..', __FILE__))
begin
require 'bundler/setup'
Bundler.require(:default)
rescue Exception
# this runs when packaged as a gem (no bundler)
require 'glimmer-dsl-libui'
# add more gems if needed
end
class #{class_name(app_name)}
APP_ROOT = File.expand_path('../..', __FILE__)
VERSION = File.read(File.join(APP_ROOT, 'VERSION'))
LICENSE = File.read(File.join(APP_ROOT, 'LICENSE.txt'))
end
require '#{file_name(app_name)}/view/#{file_name(app_name)}'
MULTI_LINE_STRING
end
def gem_main_file(custom_control_name, namespace = nil)
custom_control_file_path = ''
custom_control_file_path += "#{file_name(namespace)}/" if namespace
custom_control_file_path += "view"
custom_control_file_path += "/#{file_name(custom_control_name)}"
<<~MULTI_LINE_STRING
$LOAD_PATH.unshift(File.expand_path('..', __FILE__))
require 'glimmer-dsl-libui'
require '#{custom_control_file_path}'
MULTI_LINE_STRING
end
def app_launch_file(app_name)
<<~MULTI_LINE_STRING
require_relative '../#{file_name(app_name)}'
#{class_name(app_name)}::View::#{class_name(app_name)}.launch
MULTI_LINE_STRING
end
def app_bin_command_file(app_name_or_gem_name, custom_window_name=nil, namespace=nil)
if custom_window_name.nil?
runner = "File.expand_path('../../app/#{file_name(app_name_or_gem_name)}/launch.rb', __FILE__)"
else
runner = "File.expand_path('../../lib/#{app_name_or_gem_name}/launch.rb', __FILE__)"
end
<<~MULTI_LINE_STRING
#!/usr/bin/env ruby
runner = #{runner}
require 'glimmer/launcher'
launcher = Glimmer::Launcher.new([runner] + ARGV)
launcher.launch
MULTI_LINE_STRING
end
def gem_launch_file(gem_name, custom_window_name, namespace)
# TODO change this so that it does not mix Glimmer unto the main object
<<~MULTI_LINE_STRING
require_relative '../#{gem_name}'
#{class_name(namespace)}::View::#{class_name(custom_window_name)}.launch
MULTI_LINE_STRING
end
def gem_rakefile(custom_window_name = nil, namespace = nil, gem_name = nil)
rakefile_content = File.read('Rakefile')
lines = rakefile_content.split("\n")
require_rake_line_index = lines.index(lines.detect {|l| l.include?("require 'rake'") })
lines.insert(require_rake_line_index, "require 'glimmer/launcher'")
gem_files_line_index = lines.index(lines.detect {|l| l.include?('# dependencies defined in Gemfile') })
if custom_window_name
lines.insert(gem_files_line_index, " gem.files = Dir['VERSION', 'LICENSE.txt', 'app/**/*', 'bin/**/*', 'config/**/*', 'db/**/*', 'docs/**/*', 'fonts/**/*', 'icons/**/*', 'images/**/*', 'lib/**/*', 'script/**/*', 'sounds/**/*', 'videos/**/*']")
lines.insert(gem_files_line_index+1, " gem.require_paths = ['lib', 'app']")
lines.insert(gem_files_line_index+2, " gem.executables = ['#{file_name(custom_window_name)}']") if custom_window_name
else
lines.insert(gem_files_line_index, " gem.files = Dir['VERSION', 'LICENSE.txt', 'lib/**/*']")
end
lines << "\nrequire 'glimmer/rake_task'\n"
lines.join("\n")
end
def spec_helper_file
content = File.read('spec/spec_helper.rb')
lines = content.split("\n")
require_line_index = lines.index(lines.detect {|l| l.include?('RSpec.configure do') })
lines[require_line_index...require_line_index] = [
"require 'bundler/setup'",
'Bundler.require(:default, :development)',
]
configure_block_line_index = lines.index(lines.detect {|l| l.include?('RSpec.configure do') }) + 1
lines[configure_block_line_index...configure_block_line_index] = [
' # The following ensures rspec tests that instantiate and set Glimmer DSL controls in @target get cleaned after',
' config.after do',
' @target.dispose if @target && @target.respond_to?(:dispose)',
' Glimmer::DSL::Engine.reset',
' end',
]
lines << "\nrequire 'glimmer/rake_task'\n"
lines.join("\n")
end
def custom_window_file(custom_window_name, namespace, window_type, window_options = {})
window_options ||= {}
window_options[:custom_window_class_name] ||= 'CustomWindow'
namespace_type = class_name(namespace) == class_name(current_dir_name) ? 'class' : 'module'
custom_window_file_content = ''
if %i[gem app].include?(window_type)
custom_window_file_content += <<-MULTI_LINE_STRING
require '#{window_type == :app ? current_dir_name : namespace}/model/greeting'
MULTI_LINE_STRING
end
custom_window_file_content += <<-MULTI_LINE_STRING
#{namespace_type} #{class_name(namespace)}
module View
class #{class_name(custom_window_name)}
include Glimmer::LibUI::#{window_options[:custom_window_class_name]}
MULTI_LINE_STRING
if window_type == :gem
custom_window_file_content += <<-MULTI_LINE_STRING
APP_ROOT = File.expand_path('../../../..', __FILE__)
VERSION = File.read(File.join(APP_ROOT, 'VERSION'))
LICENSE = File.read(File.join(APP_ROOT, 'LICENSE.txt'))
MULTI_LINE_STRING
end
custom_window_file_content += <<-MULTI_LINE_STRING
## Add options like the following to configure CustomWindow by outside consumers
#
# options :title, :background_color
# option :width, default: 320
# option :height, default: 240
MULTI_LINE_STRING
custom_window_file_content += <<-MULTI_LINE_STRING
## Use before_body block to pre-initialize variables to use in body and
# to setup application menu
#
MULTI_LINE_STRING
if window_type == :app
custom_window_file_content += <<-MULTI_LINE_STRING
before_body do
@greeting = Model::Greeting.new
menu_bar
end
MULTI_LINE_STRING
elsif window_type == :gem
custom_window_file_content += <<-MULTI_LINE_STRING
before_body do
@greeting = Model::Greeting.new
end
MULTI_LINE_STRING
else
custom_window_file_content += <<-MULTI_LINE_STRING
# before_body do
#
# end
MULTI_LINE_STRING
end
custom_window_file_content += <<-MULTI_LINE_STRING
## Use after_body block to setup observers for controls in body
#
# after_body do
#
# end
## Add control content inside custom window body
## Top-most control must be a window or another custom window
#
body {
window {
# Replace example content below with your own custom window content
content_size 240, 240
title '#{human_name(namespace)}'
margined true
MULTI_LINE_STRING
if window_type == :gem
custom_window_file_content += <<-MULTI_LINE_STRING
vertical_box {
button('Preferences...') {
stretchy false
on_clicked do
display_preferences_dialog
end
}
label {
#{%i[gem app].include?(window_type) ? "text <= [@greeting, :text]" : "text '#{human_name(custom_window_name)}'"}
}
}
MULTI_LINE_STRING
else
custom_window_file_content += <<-MULTI_LINE_STRING
label {
#{%i[gem app].include?(window_type) ? "text <= [@greeting, :text]" : "text '#{human_name(custom_window_name)}'"}
}
MULTI_LINE_STRING
end
custom_window_file_content += <<-MULTI_LINE_STRING
}
}
MULTI_LINE_STRING
if %i[app].include?(window_type)
custom_window_file_content += <<-MULTI_LINE_STRING
def menu_bar
menu('File') {
menu_item('Preferences...') {
on_clicked do
display_preferences_dialog
end
}
# Enables quitting with CMD+Q on Mac with Mac Quit menu item
quit_menu_item if OS.mac?
}
menu('Help') {
if OS.mac?
about_menu_item {
on_clicked do
display_about_dialog
end
}
end
menu_item('About') {
on_clicked do
display_about_dialog
end
}
}
end
MULTI_LINE_STRING
end
if %i[gem app].include?(window_type)
custom_window_file_content += <<-MULTI_LINE_STRING
def display_about_dialog
message = "#{human_name(namespace)}#{" - #{human_name(custom_window_name)}" if window_type == :gem} \#{VERSION}\\n\\n\#{LICENSE}"
msg_box('About', message)
end
MULTI_LINE_STRING
end
if %i[gem app].include?(window_type)
custom_window_file_content += <<-MULTI_LINE_STRING
def display_preferences_dialog
window {
title 'Preferences'
content_size 200, 100
margined true
vertical_box {
padded true
label('Greeting:') {
stretchy false
}
radio_buttons {
stretchy false
items Model::Greeting::GREETINGS
selected <=> [@greeting, :text_index]
}
}
}.show
end
MULTI_LINE_STRING
end
custom_window_file_content += <<-MULTI_LINE_STRING
end
end
end
MULTI_LINE_STRING
end
def custom_control_file(custom_control_name, namespace)
namespace_type = class_name(namespace) == class_name(current_dir_name) ? 'class' : 'module'
<<-MULTI_LINE_STRING
#{namespace_type} #{class_name(namespace)}
module View
class #{class_name(custom_control_name)}
include Glimmer::LibUI::CustomControl
## Add options like the following to configure CustomControl by outside consumers
#
# options :custom_text, :background_color
# option :foreground_color, default: :red
# Replace example options with your own options
option :model
option :attributes
## Use before_body block to pre-initialize variables to use in body
#
#
before_body do
# Replace example code with your own before_body code
default_model_attributes = [:first_name, :last_name, :email]
default_model_class = Struct.new(*default_model_attributes)
self.model ||= default_model_class.new
self.attributes ||= default_model_attributes
end
## Use after_body block to setup observers for controls in body
#
# after_body do
#
# end
## Add control content under custom control body
##
## If you want to add a window as the top-most control,
## consider creating a custom window instead
## (Glimmer::LibUI::CustomWindow offers window convenience methods, like show and hide)
#
body {
# Replace example content (model_form custom control) with your own custom control content.
form {
attributes.each do |attribute|
entry { |e|
label attribute.to_s.underscore.split('_').map(&:capitalize).join(' ')
text <=> [model, attribute]
}
end
}
}
end
end
end
MULTI_LINE_STRING
end
def custom_shape_file(custom_shape_name, namespace)
namespace_type = class_name(namespace) == class_name(current_dir_name) ? 'class' : 'module'
<<-MULTI_LINE_STRING
#{namespace_type} #{class_name(namespace)}
module View
class #{class_name(custom_shape_name)}
include Glimmer::LibUI::CustomShape
## Add options like the following to configure CustomShape by outside consumers
#
# options :option1, option2, option3
option :background_color, default: :red
option :size_width, default: 100
option :size_height, default: 100
option :location_x, default: 0
option :location_y, default: 0
## Use before_body block to pre-initialize variables to use in body
#
#
# before_body do
#
# end
## Use after_body block to setup observers for shapes in body
#
# after_body do
#
# end
## Add shape content under custom shape body
#
body {
# Replace example content below (heart shape) with your own custom shape content
shape(location_x, location_y) {
# This fill color is shared under all direct children of `shape`
fill background_color
bezier(
size_width - size_width*0.66, size_height/2 - size_height*0.33,
size_width*0.65 - size_width*0.66, 0 - size_height*0.33,
size_width/2 - size_width*0.66, size_height*0.75 - size_height*0.33,
size_width - size_width*0.66, size_height - size_height*0.33
)
bezier(
size_width - size_width*0.66, size_height/2 - size_height*0.33,
size_width*1.35 - size_width*0.66, 0 - size_height*0.33,
size_width*1.5 - size_width*0.66, size_height*0.75 - size_height*0.33,
size_width - size_width*0.66, size_height - size_height*0.33
)
}
}
end
end
end
MULTI_LINE_STRING
end
def model_file(model_name, namespace)
namespace_type = class_name(namespace) == class_name(current_dir_name) ? 'class' : 'module'
<<-MULTI_LINE_STRING
# Delete this example model and replace with your own model
#{namespace_type} #{class_name(namespace)}
module Model
class #{class_name(model_name)}
GREETINGS = [
'Hello, World!',
'Howdy, Partner!'
]
attr_accessor :text
def initialize
@text = GREETINGS.first
end
def text_index=(new_text_index)
self.text = GREETINGS[new_text_index]
end
def text_index
GREETINGS.index(text)
end
end
end
end
MULTI_LINE_STRING
end
end
end
end
end