ruby_on_skis 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +88 -0
- data/Rakefile +67 -0
- data/VERSION +1 -0
- data/bin/init.rb +18 -0
- data/bin/pinit.rb +27 -0
- data/config/environment.rb +189 -0
- data/config/gemconfigure.rb +24 -0
- data/config/requires.yml +15 -0
- data/data/lorem.txt +101 -0
- data/fixtures/messages.yml +7 -0
- data/images/ruby_on_skis.ico +0 -0
- data/lib/extensions/string/truncate.rb +16 -0
- data/lib/models/message.rb +11 -0
- data/lib/wx/app/app_frame.rb +56 -0
- data/lib/wx/app/message_panel.rb +98 -0
- data/lib/wx/app/taskbar_icon.rb +26 -0
- data/lib/wx/app.xrc +1 -0
- data/lib/wx/base/appframebase.rb +46 -0
- data/lib/wx/base/messagepanelbase.rb +45 -0
- data/lib/wx/helpers/app_helper.rb +86 -0
- data/migrate/20081128200300_init.rb +14 -0
- data/package/config.yml +29 -0
- data/package/installer.nsi +185 -0
- data/ruby_on_skis.fbp +742 -0
- data/script/console +11 -0
- data/spec/config/environment_spec.rb +53 -0
- data/spec/extensions/string/truncate_spec.rb +23 -0
- data/spec/models/message_spec.rb +43 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +21 -0
- data/tasks/database.rake +20 -0
- data/tasks/mswin.rake +62 -0
- data/tasks/osx.rake +73 -0
- data/tasks/package_lib.rake +130 -0
- metadata +99 -0
data/README.textile
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
h1. Ruby on Skis
|
2
|
+
|
3
|
+
h2. Introduction
|
4
|
+
|
5
|
+
The aim of Ruby on Skis is to provide a starting structure within which to program your wxRuby project. The template provides a directory structure, a set of Rakefiles to manage, and most importantly, to _package_ your Ruby application for distribution as a standalone program when completed. It also includes an environment to get the application running and provide basic services to the program code. For now, the template only supports packaging for Mac OSX and Windows, although various flavors of Linux should be easily accommodated and are planned for the future.
|
6
|
+
|
7
|
+
h2. Audience
|
8
|
+
|
9
|
+
This template is initially aimed at Rubyists with some experience. If this is your very first Ruby project, then this template probably is not for you. This is alpha-grade software. As the work progresses, it should become a viable choice for less experienced developers.
|
10
|
+
|
11
|
+
h2. Features
|
12
|
+
|
13
|
+
* Packaging for Windows and Mac OSX into a standalone program with an installer.
|
14
|
+
* Support for inclusion of specific versions of Ruby Gems. (Active Record is included in the template as an example)
|
15
|
+
* Support for including arbitrary files needed to run specific Ruby Gems.
|
16
|
+
* A script/console command for interacting with your non-GUI code.
|
17
|
+
* Environment code that requires all of the code, and provides basic services to your code.
|
18
|
+
* Includes a basic example of creating/reading/deleting objects via ActiveRecord.
|
19
|
+
|
20
|
+
h2. Required tools
|
21
|
+
|
22
|
+
In order to use the template effectively, you must use the following tools:
|
23
|
+
|
24
|
+
* "wxRuby":http://wxruby.rubyforge.org
|
25
|
+
* "wxFormBuilder":http://wxformbuilder.org/
|
26
|
+
* XRCise tool from "wxSugar":http://wxruby.rubyforge.org/wiki/wiki.pl?WxSugar.
|
27
|
+
* "RSpec":http://rspec.info/ for testing.
|
28
|
+
* "Platypus":http://www.sveinbjorn.org/platypus packager for creating the final package on Mac OS X.
|
29
|
+
* "NSIS":http://nsis.sourceforge.net/Main_Page packager for creating the final package on Windows.
|
30
|
+
|
31
|
+
h2. General Workflow
|
32
|
+
|
33
|
+
The general workflow will be something like:
|
34
|
+
|
35
|
+
# Clone the project. Use 'rake run' in the project directory to run the project and fix any problems.
|
36
|
+
# Remove the example code.
|
37
|
+
# Name your project by redefining the app_name method in config/environment.rb
|
38
|
+
# Define Frames, Panels etc. with the appropriate Subclass names, filled with buttons, labels and other widgets with the appropriate names in wxFormBuilder.
|
39
|
+
# Press 'F8' (Generate XRC source) to create the XRC file in your project.
|
40
|
+
# Write the appropriate handlers in subclasses of the generated Wx subclasses.
|
41
|
+
# Exceute 'rake run' which will generate the GUI glue code via XRCise and run the project.
|
42
|
+
# Repeat as necessary.
|
43
|
+
# Once you are ready to package the project, examine and modify installer.nsi as necessary for the windows packager.
|
44
|
+
# Run 'rake package:mswin[1.0]' to package the project for windows. The '1.0' is the version number, use what is appropriate for your project. You must run the packaging code on Windows to create a Windows package.
|
45
|
+
# Run 'rake package:dmg[1.0]' to package the code for OSX. Again, the '1.0' is just an example, use what is appropriate for your project. You must run the packaging code on OSX to create an OSX package.
|
46
|
+
|
47
|
+
Note: Due to the way the packaging code works, you need to require everything in the environment file when the program starts up. There should be no 'requires' sprinkled throughout the code, or there is a chance that the packaging code will not find the required library and package it.
|
48
|
+
|
49
|
+
|
50
|
+
h2. Further work
|
51
|
+
|
52
|
+
Keep in mind that this template is very much a work in progress. I have used it to complete a couple of small projects, and it has worked well for that aim, but right now it is very specific to the job it does, and is pretty hacky in places. Planned work for the future:
|
53
|
+
|
54
|
+
* Instead of a template, the goal is to create a script packaged in a gem that will generate the required directory structure and generate the code that glues it all together.
|
55
|
+
* Create a DEB installer for Linux.
|
56
|
+
* Create an RPM installer for Linux.
|
57
|
+
* Generalize into a system for packaging all kinds of Ruby applications, not just those based on wxRuby.
|
58
|
+
* Create Wx mock class for unit testing Wx subclasses.
|
59
|
+
* Include Nobbie examples
|
60
|
+
* Better RSpec configuration support.
|
61
|
+
|
62
|
+
|
63
|
+
h2. A word about the included binaries
|
64
|
+
|
65
|
+
I have included Mac OSX and Windows binaries for the libraries needed to run the example code. The included binaries are from Ruby 1.8.7-p72. Including the binaries is probably not the best long-term solution, however, I feel it is the pragmatic approach to quickly get this thing off the ground. If you need a different Ruby version, feel free to replace the binaries in your project.
|
66
|
+
|
67
|
+
h2. A note on Virtual Machines
|
68
|
+
|
69
|
+
I develop on Mac OSX, then run the projects on Windows in a virtual machine, using Parallels to debug and ensure that it works in Windows. Using Parallels is recommended because it will mount your OSX drives in Windows. This way, you can still edit the source in OSX, and then simply use a command line in Windows to run the project. Once you are ready for packaging, you can simply export the project, and again just run the packager in Windows at the command line on the mounted OSX drive. This also points up the fact that the template might not work so well on Windows as the development environment, so there may be some problems with using that approach that I'm not aware of at this point. Feel free to file an issue with the Github issue tracker.
|
70
|
+
|
71
|
+
h2. Thanks
|
72
|
+
|
73
|
+
I want to give a special thanks to Alex Fenton for his post on the wxRuby forum and some of the code that it points to, which made it into the template, and otherwise paved the way for the creation of this template.
|
74
|
+
|
75
|
+
I would also like to thank the creators and contributors of wxWidgets, wxRuby and wxSugar for their outstanding work, otherwise this work would not have been possible.
|
76
|
+
|
77
|
+
I also want to thank the Rails team and contributors. You'll probably notice a certain rails-ish flavor to the template. I've also incorporated some stuff from ActiveRecord tasks into the mix, so thanks guys!
|
78
|
+
|
79
|
+
h2. License
|
80
|
+
|
81
|
+
While I really don't care about licenses much, it is probably necessary to state here that this template is hereby released under Ruby's license, which seems pretty liberal. Some kudos in your app to me would be nice if you base it on this work.
|
82
|
+
|
83
|
+
h2. Finally, Be Gentle
|
84
|
+
|
85
|
+
There are quite a few things that need work, and some things I plain don't like about the code, but it works for me on my development box. There may be things I've forgotten to include that exist on my box, which may not exist on yours. Please file reports via Github's issue tracker and I'll attempt to take care of them as I have time. The project is nowhere near polished, but I wanted to get it out there as soon as I can to give back to the community and garner feedback as I work to create a polished offering.
|
86
|
+
|
87
|
+
As with many open-source developers, I have a day job and this is a side project, please be patient.
|
88
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
config_path = File.expand_path(File.dirname(__FILE__) + '/config')
|
6
|
+
$LOAD_PATH << config_path unless $LOAD_PATH.include?(config_path)
|
7
|
+
require 'environment'
|
8
|
+
Environment.load_tasks
|
9
|
+
|
10
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
11
|
+
t.spec_files = FileList["#{Environment.spec_path}/**/*_spec.rb"]
|
12
|
+
t.spec_opts = ['--options', "#{Environment.spec_path}/spec.opts"]
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Run Project"
|
16
|
+
task :run => Environment.base_class_path do
|
17
|
+
ENV[Environment.app_env_const] = 'development'
|
18
|
+
executable = File.join( Config::CONFIG['bindir'],
|
19
|
+
Config::CONFIG['RUBY_INSTALL_NAME'] +
|
20
|
+
Config::CONFIG['EXEEXT'] )
|
21
|
+
exec("#{executable} #{Environment.app_file}")
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Generate Wx Base Classes from XRC"
|
25
|
+
file Environment.base_class_path => Environment.xrc_file do | t |
|
26
|
+
$stderr.puts "Generating GUI Base Classes"
|
27
|
+
sh "xrcise -o #{Environment.base_class_path} #{Environment.xrc_file} && touch #{Environment.base_class_path}"
|
28
|
+
make_bases_relative
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
require 'jeweler'
|
33
|
+
Jeweler::Tasks.new do |gemspec|
|
34
|
+
gemspec.name = "ruby_on_skis"
|
35
|
+
gemspec.summary = "Provide a starting structure within which to program your wxRuby project"
|
36
|
+
gemspec.description = <<-DESCRIPTION
|
37
|
+
The aim of Ruby on Skis is to provide a starting structure within which to program your wxRuby project.
|
38
|
+
The template provides a directory structure, a set of Rakefiles to manage, and most importantly, to
|
39
|
+
package your Ruby application for distribution as a standalone program when completed. It also includes
|
40
|
+
an environment to get the application running and provide basic services to the program code.
|
41
|
+
For now, the template only supports packaging for Mac OSX and Windows, although various flavors of
|
42
|
+
Linux should be easily accommodated and are planned for the future
|
43
|
+
DESCRIPTION
|
44
|
+
gemspec.email = "duskhacker@duskhacker.com"
|
45
|
+
gemspec.homepage = "http://github.com/duskhacker/ruby_on_skis"
|
46
|
+
gemspec.authors = ["Daniel P. Zepeda"]
|
47
|
+
end
|
48
|
+
rescue LoadError
|
49
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def make_bases_relative
|
54
|
+
Dir.glob(Environment.base_class_path + '/*.rb') do | file |
|
55
|
+
fh = File.open(file, "r+")
|
56
|
+
data = fh.readlines
|
57
|
+
data.each do | line |
|
58
|
+
line.gsub! /"#{Environment.xrc_file}"/, "File.dirname(__FILE__) + '/../app.xrc'"
|
59
|
+
end
|
60
|
+
fh.rewind
|
61
|
+
fh.truncate(0)
|
62
|
+
fh.puts data
|
63
|
+
fh.close
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/bin/init.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Development init. There is some common code with the production-mode 'pinit.rb',
|
2
|
+
# but it's not worth the extra effort to refactor it out, you'll probably hardly
|
3
|
+
# ever touch these files.
|
4
|
+
|
5
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../../config')
|
6
|
+
require 'environment'
|
7
|
+
env = ENV[Environment.app_env_const] || 'production'
|
8
|
+
Environment.setup(env)
|
9
|
+
title = Environment.app_name.camelize
|
10
|
+
title << " (#{ENV[Environment.app_env_const].upcase})" unless env == 'production'
|
11
|
+
|
12
|
+
unless ENV['ASSEMBLING'] == "true"
|
13
|
+
Wx::App.run do
|
14
|
+
self.app_name = title
|
15
|
+
@frame = AppFrame.new(title)
|
16
|
+
@frame.show
|
17
|
+
end
|
18
|
+
end
|
data/bin/pinit.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Production init. There is some common code with the development-mode 'init.rb',
|
2
|
+
# but it's not worth the extra effort to refactor it out, you'll probably hardly
|
3
|
+
# ever touch these files.
|
4
|
+
|
5
|
+
bundle_path = File.expand_path(File.dirname(__FILE__) + '/../lib' )
|
6
|
+
|
7
|
+
$LOAD_PATH.clear
|
8
|
+
$LOAD_PATH << "#{bundle_path}"
|
9
|
+
Dir.glob("#{bundle_path}/*") do | path |
|
10
|
+
if File.directory?(path)
|
11
|
+
$LOAD_PATH << path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'environment'
|
16
|
+
env = ENV[Environment.app_env_const] || 'production'
|
17
|
+
Environment.setup(env, true, true)
|
18
|
+
title = Environment.app_name.camelize
|
19
|
+
title << " (#{ENV[Environment.app_env_const].upcase})" unless env == 'production'
|
20
|
+
|
21
|
+
unless ENV['ASSEMBLING'] == "true"
|
22
|
+
Wx::App.run do
|
23
|
+
self.app_name = title
|
24
|
+
@frame = AppFrame.new(title)
|
25
|
+
@frame.show
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module Environment
|
2
|
+
class << self
|
3
|
+
|
4
|
+
attr_accessor :environment # Accessor for testing
|
5
|
+
|
6
|
+
# Change this for each application, many settings are
|
7
|
+
# based off of this setting.
|
8
|
+
def app_name
|
9
|
+
"RubyOnSkis"
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup(environment, load_gui_components = true, loading_from_package = false)
|
13
|
+
@environment = environment
|
14
|
+
$LOAD_PATH << ( app_root + '/config' )
|
15
|
+
require_libs(load_gui_components, loading_from_package)
|
16
|
+
Dir.mkdir( data_path ) unless File.exists?(data_path)
|
17
|
+
backup_database
|
18
|
+
establish_connection
|
19
|
+
migrate
|
20
|
+
load_fixtures
|
21
|
+
end
|
22
|
+
|
23
|
+
def require_libs(load_gui_components=true, loading_from_package=false)
|
24
|
+
require 'yaml'
|
25
|
+
config = YAML.load_file(app_root + '/config/requires.yml')
|
26
|
+
|
27
|
+
# Only do this when in development mode
|
28
|
+
unless loading_from_package
|
29
|
+
require 'gemconfigure'
|
30
|
+
gem_config = []
|
31
|
+
|
32
|
+
config.each_pair do | name, values |
|
33
|
+
next if !load_gui_components && name =~/wx/
|
34
|
+
gem_config << [name, values["version"]]
|
35
|
+
end
|
36
|
+
|
37
|
+
Gem.configure(gem_config)
|
38
|
+
end
|
39
|
+
|
40
|
+
config.each_pair do | name, values |
|
41
|
+
next if !load_gui_components && name =~/wx/
|
42
|
+
require values["require"]
|
43
|
+
end
|
44
|
+
|
45
|
+
# app-specific
|
46
|
+
|
47
|
+
require 'find'
|
48
|
+
Find.find(File.expand_path(File.dirname(__FILE__) + '/../lib')) do | path |
|
49
|
+
Find.prune if !File.directory?(path) || File.basename(path).index('.') == 0
|
50
|
+
$LOAD_PATH << path
|
51
|
+
end
|
52
|
+
|
53
|
+
app_files = Dir.glob( app_root + '/lib/extensions/**/*.rb')
|
54
|
+
app_files += Dir.glob( app_root + '/lib/models/*.rb')
|
55
|
+
|
56
|
+
if load_gui_components
|
57
|
+
app_files += Dir.glob( "#{base_class_path}/*.rb")
|
58
|
+
app_files += Dir.glob( app_root + '/lib/wx/helpers/*.rb')
|
59
|
+
app_files += Dir.glob( app_root + '/lib/wx/app/*.rb')
|
60
|
+
end
|
61
|
+
|
62
|
+
app_files.each do | file |
|
63
|
+
require file.gsub(/#{app_root}\/lib\//, '')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def establish_connection
|
68
|
+
unless production?
|
69
|
+
ActiveRecord::Base.logger = Logger.new("#{data_path}/#{environment}.log")
|
70
|
+
ActiveRecord::Base.logger.level = Logger::DEBUG
|
71
|
+
end
|
72
|
+
ActiveRecord::Base.establish_connection(
|
73
|
+
:adapter => "sqlite3",
|
74
|
+
:dbfile => db_file
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def migrate
|
79
|
+
if production?
|
80
|
+
ActiveRecord::Migration.verbose=false
|
81
|
+
ActiveRecord::Base.logger = Logger.new("#{data_path}/#{environment}.log")
|
82
|
+
end
|
83
|
+
|
84
|
+
ActiveRecord::Migrator.migrate(app_root + "/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
85
|
+
ActiveRecord::Base.logger = nil if production?
|
86
|
+
end
|
87
|
+
|
88
|
+
def load_fixtures
|
89
|
+
fixture_files = Dir.glob(app_root + "/fixtures/*.{yml,csv}")
|
90
|
+
return if fixture_files.empty?
|
91
|
+
require 'active_record/fixtures'
|
92
|
+
fixture_files.each do |fixture_file|
|
93
|
+
klass = File.basename(fixture_file).gsub(/\.yml/,'').titleize.singularize.constantize
|
94
|
+
next if klass.count > 0
|
95
|
+
Fixtures.create_fixtures( app_root + '/fixtures', File.basename(fixture_file, '.yml'))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_tasks
|
100
|
+
Dir["#{Environment.app_root}/tasks/**/*.rake"].sort.each { |ext| load ext }
|
101
|
+
end
|
102
|
+
|
103
|
+
def db_file(env=environment)
|
104
|
+
File.join(data_path, "#{app_name.underscore}_#{env}.db")
|
105
|
+
end
|
106
|
+
|
107
|
+
def xrc_file
|
108
|
+
"#{app_root}/lib/wx/app.xrc"
|
109
|
+
end
|
110
|
+
|
111
|
+
def base_class_path
|
112
|
+
"#{app_root}/lib/wx/base"
|
113
|
+
end
|
114
|
+
|
115
|
+
def app_file
|
116
|
+
"#{app_root}/bin/common/init.rb"
|
117
|
+
end
|
118
|
+
|
119
|
+
def spec_path
|
120
|
+
"#{app_root}/spec"
|
121
|
+
end
|
122
|
+
|
123
|
+
def app_root
|
124
|
+
File.expand_path(File.dirname(__FILE__) + '/../')
|
125
|
+
end
|
126
|
+
|
127
|
+
def app_env_const
|
128
|
+
app_name.upcase + "_ENV"
|
129
|
+
end
|
130
|
+
|
131
|
+
def have_console?
|
132
|
+
open("CONOUT$", "w") {}
|
133
|
+
true
|
134
|
+
rescue SystemCallError
|
135
|
+
false
|
136
|
+
end
|
137
|
+
|
138
|
+
def data_path
|
139
|
+
@data_path ||= if mswin?
|
140
|
+
File.expand_path(File.join(ENV['APPDATA'].gsub(/\\/,'/'), app_name.camelize))
|
141
|
+
else
|
142
|
+
"#{ENV['HOME']}/.#{app_name.underscore}/"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def tmpdir
|
147
|
+
if mswin?
|
148
|
+
ENV['TMP'] || ENV['TEMP']
|
149
|
+
else
|
150
|
+
ENV['TMPDIR']
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def production?
|
155
|
+
environment == "production"
|
156
|
+
end
|
157
|
+
|
158
|
+
def development?
|
159
|
+
environment == "development"
|
160
|
+
end
|
161
|
+
|
162
|
+
def test?
|
163
|
+
environment == "test"
|
164
|
+
end
|
165
|
+
|
166
|
+
def mswin?
|
167
|
+
RUBY_PLATFORM == 'i386-mswin32'
|
168
|
+
end
|
169
|
+
|
170
|
+
def darwin?
|
171
|
+
RUBY_PLATFORM == 'i686-darwin9'
|
172
|
+
end
|
173
|
+
|
174
|
+
def backup_database
|
175
|
+
return unless Environment.production?
|
176
|
+
file_index_matcher = /#{File.basename(Environment.db_file)}\.(\d)$/
|
177
|
+
Dir.glob("#{Environment.db_file}.*").sort.reverse.each do | file |
|
178
|
+
next if file == "#{Environment.db_file}.#{backup_limit}"
|
179
|
+
file_index = file_index_matcher.match(file)[1].to_i
|
180
|
+
FileUtils.mv file, "#{Environment.db_file}.#{file_index+1}"
|
181
|
+
end
|
182
|
+
FileUtils.cp(Environment.db_file, "#{Environment.db_file}.1") if File.exists?(Environment.db_file)
|
183
|
+
end
|
184
|
+
|
185
|
+
def backup_limit
|
186
|
+
10
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
module Gem
|
8
|
+
|
9
|
+
# Activate the gems specfied by the gem_pairs list.
|
10
|
+
#
|
11
|
+
# gem_pairs ::
|
12
|
+
# List of gem/version pairs.
|
13
|
+
# Eg. [['rake', '= 0.8.15'], ['RedCloth', '~> 3.0']]
|
14
|
+
# options ::
|
15
|
+
# options[:verbose] => print gems as they are required.
|
16
|
+
#
|
17
|
+
def self.configure(gem_pairs, options={})
|
18
|
+
gem_pairs.each do |name, version|
|
19
|
+
require 'rubygems'
|
20
|
+
puts "Activating gem #{name} (version #{version})" if options[:verbose]
|
21
|
+
gem name, version
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/config/requires.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Include the gems and the versions you want to use here. This file is only used in production,
|
2
|
+
# when the program is packaged, this file is ignored in favor of what is available in the package.
|
3
|
+
---
|
4
|
+
activerecord:
|
5
|
+
require: activerecord
|
6
|
+
version: =2.2.2
|
7
|
+
activesupport:
|
8
|
+
require: activesupport
|
9
|
+
version: =2.2.2
|
10
|
+
sqlite3-ruby:
|
11
|
+
require: sqlite3
|
12
|
+
version: =1.2.3
|
13
|
+
wxruby:
|
14
|
+
require: wx
|
15
|
+
version: =2.0.0
|
data/data/lorem.txt
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
|
2
|
+
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
|
3
|
+
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
4
|
+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
|
5
|
+
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident,
|
6
|
+
sunt in culpa qui officia deserunt mollit anim id est laborum.
|
7
|
+
|
8
|
+
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius,
|
9
|
+
turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis
|
10
|
+
sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus
|
11
|
+
et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut
|
12
|
+
ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt
|
13
|
+
sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum.
|
14
|
+
Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget,
|
15
|
+
consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl
|
16
|
+
adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque
|
17
|
+
nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis,
|
18
|
+
laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu,
|
19
|
+
feugiat in, orci. In hac habitasse platea dictumst.
|
20
|
+
|
21
|
+
Fusce convallis, mauris imperdiet gravida bibendum, nisl turpis suscipit
|
22
|
+
mauris, sed placerat ipsum urna sed risus. In convallis tellus a mauris.
|
23
|
+
Curabitur non elit ut libero tristique sodales. Mauris a lacus. Donec mattis
|
24
|
+
semper leo. In hac habitasse platea dictumst. Vivamus facilisis diam at odio.
|
25
|
+
Mauris dictum, nisi eget consequat elementum, lacus ligula molestie metus, non
|
26
|
+
feugiat orci magna ac sem. Donec turpis. Donec vitae metus. Morbi tristique
|
27
|
+
neque eu mauris. Quisque gravida ipsum non sapien. Proin turpis lacus,
|
28
|
+
scelerisque vitae, elementum at, lobortis ac, quam. Aliquam dictum eleifend
|
29
|
+
risus. In hac habitasse platea dictumst. Etiam sit amet diam. Suspendisse odio.
|
30
|
+
Suspendisse nunc. In semper bibendum libero.
|
31
|
+
|
32
|
+
Proin nonummy, lacus eget pulvinar lacinia, pede felis dignissim leo, vitae
|
33
|
+
tristique magna lacus sit amet eros. Nullam ornare. Praesent odio ligula,
|
34
|
+
dapibus sed, tincidunt eget, dictum ac, nibh. Nam quis lacus. Nunc eleifend
|
35
|
+
molestie velit. Morbi lobortis quam eu velit. Donec euismod vestibulum massa.
|
36
|
+
Donec non lectus. Aliquam commodo lacus sit amet nulla. Cras dignissim elit et
|
37
|
+
augue. Nullam non diam. Pellentesque habitant morbi tristique senectus et netus
|
38
|
+
et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Aenean
|
39
|
+
vestibulum. Sed lobortis elit quis lectus. Nunc sed lacus at augue bibendum dapibus.
|
40
|
+
|
41
|
+
Aliquam vehicula sem ut pede. Cras purus lectus, egestas eu, vehicula at,
|
42
|
+
imperdiet sed, nibh. Morbi consectetuer luctus felis. Donec vitae nisi. Aliquam
|
43
|
+
tincidunt feugiat elit. Duis sed elit ut turpis ullamcorper feugiat. Praesent
|
44
|
+
pretium, mauris sed fermentum hendrerit, nulla lorem iaculis magna, pulvinar
|
45
|
+
scelerisque urna tellus a justo. Suspendisse pulvinar massa in metus. Duis quis
|
46
|
+
quam. Proin justo. Curabitur ac sapien. Nam erat. Praesent ut quam.
|
47
|
+
|
48
|
+
Vivamus commodo, augue et laoreet euismod, sem sapien tempor dolor, ac egestas
|
49
|
+
sem ligula quis lacus. Donec vestibulum tortor ac lacus. Sed posuere vestibulum
|
50
|
+
nisl. Curabitur eleifend fermentum justo. Nullam imperdiet. Integer sit amet
|
51
|
+
mauris imperdiet risus sollicitudin rutrum. Ut vitae turpis. Nulla facilisi.
|
52
|
+
Quisque tortor velit, scelerisque et, facilisis vel, tempor sed, urna. Vivamus
|
53
|
+
nulla elit, vestibulum eget, semper et, scelerisque eget, lacus. Pellentesque
|
54
|
+
viverra purus. Quisque elit. Donec ut dolor.
|
55
|
+
|
56
|
+
Duis volutpat elit et erat. In at nulla at nisl condimentum aliquet. Quisque
|
57
|
+
elementum pharetra lacus. Nunc gravida arcu eget nunc. Nulla iaculis egestas
|
58
|
+
magna. Aliquam erat volutpat. Sed pellentesque orci. Etiam lacus lorem, iaculis
|
59
|
+
sit amet, pharetra quis, imperdiet sit amet, lectus. Integer quis elit ac mi
|
60
|
+
aliquam pretium. Nullam mauris orci, porttitor eget, sollicitudin non,
|
61
|
+
vulputate id, risus. Donec varius enim nec sem. Nam aliquam lacinia enim.
|
62
|
+
Quisque eget lorem eu purus dignissim ultricies. Fusce porttitor hendrerit
|
63
|
+
ante. Mauris urna diam, cursus id, mattis eget, tempus sit amet, risus.
|
64
|
+
Curabitur eu felis. Sed eu mi. Nullam lectus mauris, luctus a, mattis ac,
|
65
|
+
tempus non, leo. Cras mi nulla, rhoncus id, laoreet ut, ultricies id, odio.
|
66
|
+
|
67
|
+
Donec imperdiet. Vestibulum auctor tortor at orci. Integer semper, nisi eget
|
68
|
+
suscipit eleifend, erat nisl hendrerit justo, eget vestibulum lorem justo ac
|
69
|
+
leo. Integer sem velit, pharetra in, fringilla eu, fermentum id, felis.
|
70
|
+
Vestibulum sed felis. In elit. Praesent et pede vel ante dapibus condimentum.
|
71
|
+
Donec magna. Quisque id risus. Mauris vulputate pellentesque leo. Duis
|
72
|
+
vulputate, ligula at venenatis tincidunt, orci nunc interdum leo, ac egestas
|
73
|
+
elit sem ut lacus. Etiam non diam quis arcu egestas commodo. Curabitur nec
|
74
|
+
massa ac massa gravida condimentum. Aenean id libero. Pellentesque vitae
|
75
|
+
tellus. Fusce lectus est, accumsan ac, bibendum sed, porta eget, augue. Etiam
|
76
|
+
faucibus. Quisque tempus purus eu ante.
|
77
|
+
|
78
|
+
Vestibulum sapien nisl, ornare auctor, consectetuer quis, posuere tristique,
|
79
|
+
odio. Fusce ultrices ullamcorper odio. Ut augue nulla, interdum at, adipiscing
|
80
|
+
non, tristique eget, neque. Pellentesque habitant morbi tristique senectus et
|
81
|
+
netus et malesuada fames ac turpis egestas. Ut pede est, condimentum id,
|
82
|
+
scelerisque ac, malesuada non, quam. Proin eu ligula ac sapien suscipit
|
83
|
+
blandit. Suspendisse euismod. Ut accumsan, neque id gravida luctus, arcu pede
|
84
|
+
sodales felis, vel blandit massa arcu eget ligula. Aenean sed turpis.
|
85
|
+
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac
|
86
|
+
turpis egestas. Donec sem eros, ornare ut, commodo eu, tempor nec, risus. Donec
|
87
|
+
laoreet dapibus ligula. Praesent orci leo, bibendum nec, ornare et, nonummy in,
|
88
|
+
elit. Donec interdum feugiat leo. Vestibulum ante ipsum primis in faucibus orci
|
89
|
+
luctus et ultrices posuere cubilia Curae; Pellentesque feugiat ullamcorper
|
90
|
+
ipsum. Donec convallis tincidunt urna.
|
91
|
+
|
92
|
+
Suspendisse et orci et arcu porttitor pellentesque. Sed lacus nunc, fermentum
|
93
|
+
vel, vehicula in, imperdiet eget, urna. Nam consectetuer euismod nunc. Nulla
|
94
|
+
dignissim posuere nulla. Integer iaculis lacinia massa. Nullam sapien augue,
|
95
|
+
condimentum vel, venenatis id, rhoncus pellentesque, sapien. Donec sed ipsum
|
96
|
+
ultrices turpis consectetuer imperdiet. Duis et ipsum ac nisl laoreet commodo.
|
97
|
+
Mauris eu est. Suspendisse id turpis quis orci euismod consequat. Donec tellus
|
98
|
+
mi, luctus sit amet, ultrices a, convallis eu, lorem. Proin faucibus convallis
|
99
|
+
elit. Maecenas rhoncus arcu at arcu. Proin libero. Proin adipiscing. In quis
|
100
|
+
lorem vitae elit consectetuer pretium. Nullam ligula urna, adipiscing nec,
|
101
|
+
iaculis ut, elementum non, turpis. Fusce pulvinar.
|
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Extensions
|
2
|
+
module String
|
3
|
+
module Truncate
|
4
|
+
|
5
|
+
def truncate(size = 20)
|
6
|
+
ellipsis = "..."
|
7
|
+
return self if size < ellipsis.size || self.size == ellipsis.size
|
8
|
+
size -= ellipsis.size
|
9
|
+
self.size > size ? self.slice(0,size) + "..." : self
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
String.send :include, Extensions::String::Truncate
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Message < ActiveRecord::Base
|
2
|
+
validates_presence_of :name, :content
|
3
|
+
validates_uniqueness_of :name
|
4
|
+
|
5
|
+
named_scope :ordered_by_name, :order => "name COLLATE NOCASE"
|
6
|
+
|
7
|
+
def self.names
|
8
|
+
connection.select_values("SELECT name FROM messages ORDER BY name COLLATE NOCASE")
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# AppFrameBase will be defined by the XRC generated from
|
2
|
+
# wxFormBuilder. Use the "Subclass" property in wxFB to define
|
3
|
+
# it.
|
4
|
+
class AppFrame < AppFrameBase
|
5
|
+
include AppHelper
|
6
|
+
|
7
|
+
def initialize(title)
|
8
|
+
super()
|
9
|
+
|
10
|
+
if Environment.darwin?
|
11
|
+
@tbicon = MyTaskBarIcon.new(self)
|
12
|
+
elsif Environment.mswin?
|
13
|
+
icon_file = File.join(Environment.app_root, 'images', "#{Environment.app_name.underscore}.ico")
|
14
|
+
icon = Wx::Icon.new(icon_file, Wx::BITMAP_TYPE_ICO)
|
15
|
+
set_icon(icon)
|
16
|
+
end
|
17
|
+
|
18
|
+
evt_menu Wx::ID_EXIT, :on_quit
|
19
|
+
evt_menu Wx::ID_ABOUT, :on_about
|
20
|
+
|
21
|
+
evt_menu quit_menu_item, :on_quit
|
22
|
+
|
23
|
+
self.title = title
|
24
|
+
self.size = [ 1024, 868 ]
|
25
|
+
|
26
|
+
self.status_text = "Welcome to #{Environment.app_name}!"
|
27
|
+
status_bar.set_min_height 80
|
28
|
+
|
29
|
+
# The apps I've written so far are single window affairs with several notebook pages. wxFormBuilder doesn't seem to
|
30
|
+
# support this directly, so creating an AppFrame, and then the notebook pages as separate panels, and tying them together
|
31
|
+
# here seems to work well.
|
32
|
+
message_panel = MessagePanel.new(notebook)
|
33
|
+
notebook.add_page(message_panel, "Messages")
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_quit
|
37
|
+
@tbicon.remove_icon unless @tbicon.nil?
|
38
|
+
destroy()
|
39
|
+
exit()
|
40
|
+
end
|
41
|
+
|
42
|
+
# show an 'About' dialog
|
43
|
+
def on_about
|
44
|
+
# TODO: Make version dynamic somehow.
|
45
|
+
msg = sprintf("Welcome to #{Environment.app_name}, version 0.1")
|
46
|
+
|
47
|
+
# create a simple message dialog with OK button
|
48
|
+
about_dlg = Wx::MessageDialog.new( self, msg, "About #{Environment.app_name}",
|
49
|
+
Wx::OK|Wx::ICON_INFORMATION )
|
50
|
+
about_dlg.show_modal
|
51
|
+
end
|
52
|
+
end
|
53
|
+
# icon_file = File.join( File.dirname(__FILE__), "mondrian.png")
|
54
|
+
# # PNG can be used on all platforms, but icon type must be specified
|
55
|
+
# # to work on Windows; OS X doesn't have "Frame" icons.
|
56
|
+
# self.icon = Wx::Icon.new(icon_file, Wx::BITMAP_TYPE_PNG)
|