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 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
@@ -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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ message_001:
3
+ name: First
4
+ content: Hello
5
+ message_002:
6
+ name: Second
7
+ content: World
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)