diff --git a/Notes.md b/Notes.md new file mode 100644 index 0000000..f2629aa --- /dev/null +++ b/Notes.md @@ -0,0 +1,58 @@ +# What is this? +This document explains the extra syntactic sugar JRubyFX applies to JavaFX. All Java-style versions always work, this is just special ruby versions of the syntax. + +# Enums and constants (including Color) +All JavaFX enums and some constants can be specified as a ruby symbol in setters and constructors. This includes most usages of `Color`. +If you have a constant or enum that is not being converted to a Java enum properly (easy to spot because of `Exception running Application: #`), it is proabbly a bug and please report it. Note that you must use either the `build` family of functions (`build`, `with`, and DSL _class_type_()), or the snake_cased= version of the setter. setProperty is not overridden in case you want to avoid conversions. + +### Example +The following two lines are equivilent + + stage.init_style = :transparent + + stage.init_style = StageStyle::TRANSPARENT + +Some Non-enum constants also work: + + timeline.cycle_count = :indefinite + +# Duration +Any duration can be specified the java way (`Duration.millis(500)`) or with the monkey-patched Number class: + + 500.ms # => Duration.millis(500) + 2.sec # => Duration.seconds(2) + 20.min # => Duration.minutes(20) + 24.hrs # => Duration.hours(24) + 1.hr # => Duration.hours(1) + +# Animation +There are three types of animation syntaxes: Java style, multiple style, and single style. Java style is just java, use google for examples. + +### Single Style +Animate is a method on the timeline: + + rectangle(x: 10, y: 40, width: 50, height: 50, fill: :red) do + # note we must save this here as the property is + # on the rectangle, not the timeline + translate_x = translateXProperty + timeline(cycle_count: :indefinite, auto_reverse: true) do + # animates given property for given timeline + # marks, over given values + animate translate_x, 0.sec => 1.sec, 0 => 200 + end.play # play immediatly + end + +### Multiple Style +This is for creating actual transition objects: + + transition = parallel_transition(:node => self) do + rotate_transition(duration: 5.sec, angle: {0 => 360}) + fade_transition(duration: 5.sec, value: {0.0 => 1.0}) + scale_transition(duration: 5.sec, x: {0.0 => 1.0}, y: {0.0 => 1.0}) + end + +Some classes are probbably missing this, please report this. + +# Builder methods +Many classes have automatic adding of children, like Panels and Timelines. To utilize, create the object inside one of the builders (build, with, or the DSL _class_name_). See the analog_clock example for details. + diff --git a/README.md b/README.md index 9bdbb3d..ac656cf 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,13 @@ The syntax of the FXML side of JRubyFX should be fairly stable, but the JavaFX D At this point in time, no custom ruby controls are supported from FXML, though you can certainly create them in code. -Build +Install +----- +```text +gem install jrubyfx +``` + +Manual Build and Install ----- Build is done using rake/gem/bundler/rdoc. You obviously need JRuby, Java 1.7 (with JavaFX) also. @@ -61,7 +67,7 @@ Require the 'jrubyfx' file/gem, and subclass JRubyFX::Application (and JRubyFX:: At the bottom of the file, call _yourFXApplicationClass_.launch(). Override start(stage) in the application. See samples/fxml/Demo.rb for commented FXML example, or the fils in samples/javafx for non-FXML (programatic JavaFX, but you should really -look into FXML, its better) or see the Getting Started Guide. +look into FXML, its better) or see the Getting Started Guide and the Notes. If you want rdoc, run `rake rdoc`. @@ -74,6 +80,7 @@ Issues as above. * Errors loading jfxrt.jar are bugs. Please report if you encounter this issue, tell us your platform, OS, and version of JRuby +* Jarify command needs the `jar` executable in your path. * Any other difficulties are bugs. Please report them License diff --git a/lib/jrubyfx/core_ext/column_constraints.rb b/lib/jrubyfx/core_ext/column_constraints.rb new file mode 100644 index 0000000..5f5a8c4 --- /dev/null +++ b/lib/jrubyfx/core_ext/column_constraints.rb @@ -0,0 +1,41 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX Column Constraints +class Java::javafx::scene::layout::ColumnConstraints + extend JRubyFX::Utils::CommonConverters + + constrain = map_converter(constrain_to_pref: CONSTRAIN_TO_PREF, + constrain: CONSTRAIN_TO_PREF, + pref: CONSTRAIN_TO_PREF, + preferred: CONSTRAIN_TO_PREF) + + converter_for :new, [], [:none], [:none, :none, constrain], [:none, :none, constrain, :none, :none, :none] + +end + +# JRubyFX DSL extensions for JavaFX Row Constraints +class Java::javafx::scene::layout::RowConstraints + extend JRubyFX::Utils::CommonConverters + + constrain = map_converter(constrain_to_pref: CONSTRAIN_TO_PREF, + constrain: CONSTRAIN_TO_PREF, + pref: CONSTRAIN_TO_PREF, + preferred: CONSTRAIN_TO_PREF) + + converter_for :new, [], [:none], [:none, :none, constrain], [:none, :none, constrain, :none, :none, :none] + +end diff --git a/lib/jrubyfx/core_ext/effects.rb b/lib/jrubyfx/core_ext/effects.rb new file mode 100644 index 0000000..07d5b8a --- /dev/null +++ b/lib/jrubyfx/core_ext/effects.rb @@ -0,0 +1,30 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX drop shadows +class Java::javafx::scene::effect::DropShadow + extend JRubyFX::Utils::CommonConverters + + converter_for :color, [:color] + + class << self + extend JRubyFX::Utils::CommonConverters + + converter_for :new, [], [:none, :color], [:none, :none, :none, :color], + [enum_converter(Java::javafx::scene::effect::BlurType), :color, :none, :none, :none, :none] + end + +end diff --git a/lib/jrubyfx/core_ext/media_player.rb b/lib/jrubyfx/core_ext/media_player.rb new file mode 100644 index 0000000..131c21e --- /dev/null +++ b/lib/jrubyfx/core_ext/media_player.rb @@ -0,0 +1,23 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX color stops +class Java::javafx::scene::media::MediaPlayer + extend JRubyFX::Utils::CommonConverters + + converter_for :cycle_count, [map_converter(indefinite: INDEFINITE)] + +end diff --git a/lib/jrubyfx/core_ext/pagination.rb b/lib/jrubyfx/core_ext/pagination.rb new file mode 100644 index 0000000..f7ac7d5 --- /dev/null +++ b/lib/jrubyfx/core_ext/pagination.rb @@ -0,0 +1,26 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX Progress * +class Java::javafx::scene::control::Pagination + extend JRubyFX::Utils::CommonConverters + + indeterm_map = map_converter(indeterminate: INDETERMINATE) + + converter_for :page_count, [indeterm_map] + converter_for :new, [], [indeterm_map], [indeterm_map, :none] + +end diff --git a/lib/jrubyfx/core_ext/progress_indicator.rb b/lib/jrubyfx/core_ext/progress_indicator.rb new file mode 100644 index 0000000..0e1ba8e --- /dev/null +++ b/lib/jrubyfx/core_ext/progress_indicator.rb @@ -0,0 +1,38 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX Progress * +class Java::javafx::scene::control::ProgressIndicator + extend JRubyFX::Utils::CommonConverters + + progress_conv = map_converter(indeterminate_progress: INDETERMINATE_PROGRESS, + indeterminate: INDETERMINATE_PROGRESS) + + converter_for :progress, [progress_conv] + converter_for :new, [], [progress_conv] + +end +# JRubyFX DSL extensions for JavaFX Progress * +class Java::javafx::scene::control::ProgressBar + extend JRubyFX::Utils::CommonConverters + + progress_conv = map_converter(indeterminate_progress: INDETERMINATE_PROGRESS, + indeterminate: INDETERMINATE_PROGRESS) + + converter_for :progress, [progress_conv] + converter_for :new, [], [progress_conv] + +end diff --git a/lib/jrubyfx/core_ext/radial_gradient.rb b/lib/jrubyfx/core_ext/radial_gradient.rb index b22e3c5..9c0997e 100644 --- a/lib/jrubyfx/core_ext/radial_gradient.rb +++ b/lib/jrubyfx/core_ext/radial_gradient.rb @@ -25,3 +25,13 @@ class << self converter_for :new, [:none, :none, :none, :none, :none, :none, enum_converter(CycleMethod), :none] end end + +# JRubyFX DSL extensions for JavaFX Linear Gradients +class Java::javafx::scene::paint::LinearGradient + class << self + java_import Java::javafx.scene.paint.CycleMethod + extend JRubyFX::Utils::CommonConverters + + converter_for :new, [:none, :none, :none, :none, :none, enum_converter(CycleMethod), :none] + end +end diff --git a/lib/jrubyfx/core_ext/region.rb b/lib/jrubyfx/core_ext/region.rb new file mode 100644 index 0000000..3a2639d --- /dev/null +++ b/lib/jrubyfx/core_ext/region.rb @@ -0,0 +1,39 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX color stops +class Java::javafx::scene::layout::Region + extend JRubyFX::Utils::CommonConverters + + use_sizes = map_converter(use_pref_size: USE_PREF_SIZE, + use_computed_size: USE_COMPUTED_SIZE, + pref_size: USE_PREF_SIZE, + computed_size: USE_COMPUTED_SIZE, + preferred_size: USE_PREF_SIZE, + compute_size: USE_COMPUTED_SIZE, + pref: USE_PREF_SIZE, + computed: USE_COMPUTED_SIZE, + preferred: USE_PREF_SIZE, + compute: USE_COMPUTED_SIZE) + + converter_for :min_width, [use_sizes] + converter_for :min_height, [use_sizes] + converter_for :pref_width, [use_sizes] + converter_for :pref_height, [use_sizes] + converter_for :max_width, [use_sizes] + converter_for :max_height, [use_sizes] + +end diff --git a/lib/jrubyfx/core_ext/rotate.rb b/lib/jrubyfx/core_ext/rotate.rb new file mode 100644 index 0000000..714daa3 --- /dev/null +++ b/lib/jrubyfx/core_ext/rotate.rb @@ -0,0 +1,37 @@ +=begin +JRubyFX - Write JavaFX and FXML in Ruby +Copyright (C) 2013 The JRubyFX Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +=end +# JRubyFX DSL extensions for JavaFX color stops +class Java::javafx::scene::transform::Rotate + extend JRubyFX::Utils::CommonConverters + + @@axis_conversions = map_converter(x_axis: X_AXIS, + y_axis: Y_AXIS, + z_axis: Z_AXIS, + x: X_AXIS, + y: Y_AXIS, + z: Z_AXIS) + + converter_for :axis, [@@axis_conversions] + + class << self + extend JRubyFX::Utils::CommonConverters + + converter_for :new, [], [:none], [:none, @axis_conversions], [:none, :none, :none], + [:none, :none, :none, :none], [:none, :none, :none, :none, @axis_conversions] + end + +end diff --git a/lib/jrubyfx/core_ext/table_view.rb b/lib/jrubyfx/core_ext/table_view.rb index 06b394a..8b61b25 100644 --- a/lib/jrubyfx/core_ext/table_view.rb +++ b/lib/jrubyfx/core_ext/table_view.rb @@ -21,7 +21,15 @@ class Java::javafx::scene::control::TableView java_import Java::javafx.scene.control.TableColumn include JRubyFX::DSL + extend JRubyFX::Utils::CommonConverters include_add :get_columns include_method_missing TableColumn + + resize_policy = map_converter(unconstrained_resize_policy: UNCONSTRAINED_RESIZE_POLICY, + constrained_resize_policy: CONSTRAINED_RESIZE_POLICY, + unconstrained: UNCONSTRAINED_RESIZE_POLICY, + constrained: CONSTRAINED_RESIZE_POLICY) + + converter_for :column_resize_policy, [resize_policy] end diff --git a/lib/jrubyfx/dsl.rb b/lib/jrubyfx/dsl.rb index 85bf59c..fae95aa 100644 --- a/lib/jrubyfx/dsl.rb +++ b/lib/jrubyfx/dsl.rb @@ -206,14 +206,11 @@ def self.inject_enum_method_converter(jfunc, in_class) # This loads the entire DSL. Call this immediately after requiring # this file, but not inside this file, or it requires itself twice. def self.load_dsl - # we must load it AFTER we finish declaring the DSL class - # This loads all custom DSL overrides that exist - JRubyFX::DSL::NAME_TO_CLASSES.each do |name, cls| - require_relative "core_ext/#{name}" if File.exists? "#{File.dirname(__FILE__)}/core_ext/#{name}.rb" + rt = "#{File.dirname(__FILE__)}/core_ext/" + Dir.foreach rt do |file| + require_relative "core_ext/#{file}" unless [".", ".."].include? file end - # observable_value is not in the list, so include it manually - require_relative 'core_ext/observable_value' - + JRubyFX::DSL.load_enum_converter() end end diff --git a/lib/jrubyfx/jfx_imports.rb b/lib/jrubyfx/jfx_imports.rb index 5e109e4..b30d845 100644 --- a/lib/jrubyfx/jfx_imports.rb +++ b/lib/jrubyfx/jfx_imports.rb @@ -22,11 +22,20 @@ if ENV['JFX_DIR'] $LOAD_PATH << ENV['JFX_DIR'] else #should we check for 1.7 vs 1.8? oh well, adding extra paths won't hurt anybody (maybe performance loading) - $LOAD_PATH << ENV_JAVA["sun.boot.library.path"].gsub(/[\/\\][amdix345678_]+$/, "") # strip i386 or amd64 (including variants). TODO: ARM + jfx_path = ENV_JAVA["sun.boot.library.path"] + $LOAD_PATH << if jfx_path.include? ":\\" and !jfx_path.include? "/" # can be tricked, but should work fine + #windows + jfx_path.gsub(/\\bin[\\]*$/i, "\\lib") + else + # *nix + jfx_path.gsub(/[\/\\][amdix345678_]+$/, "") # strip i386 or amd64 (including variants). TODO: ARM + end end require 'jfxrt.jar' -rescue - fail "JavaFX runtime not found. Please install Java 7u4 or newer or set environment variable JAVAFX_DIR to the folder that contains jfxrt.jar" +rescue LoadError + puts "JavaFX runtime not found. Please install Java 7u6 or newer or set environment variable JFX_DIR to the folder that contains jfxrt.jar " + puts "If you have Java 7u6 or later, this is a bug. Please report to the issue tracker on github. Include your OS version, 32/64bit, and architecture (x86, ARM, PPC, etc)" + exit -1 end module JRubyFX diff --git a/lib/jrubyfx/utils/common_converters.rb b/lib/jrubyfx/utils/common_converters.rb index 705dd8e..ee3ee48 100644 --- a/lib/jrubyfx/utils/common_converters.rb +++ b/lib/jrubyfx/utils/common_converters.rb @@ -25,29 +25,13 @@ module CommonConverters # map of snake_cased colors to JavaFX Colors NAME_TO_COLORS = { - 'black' => Color::BLACK, - 'blue' => Color::BLUE, - 'cyan' => Color::CYAN, - 'cadet_blue' => Color::CADETBLUE, - 'dark_blue' => Color::DARKBLUE, - 'dark_cyan' => Color::DARKCYAN, - 'dark_green' => Color::DARKGREEN, - 'dark_magenta' => Color::DARKMAGENTA, - 'dark_red' => Color::DARKRED, - 'dark_yellow' => Color.web('0xc0c000'), - 'green' => Color::GREEN, - 'light_blue' => Color::LIGHTBLUE, - 'light_cyan' => Color::LIGHTCYAN, - 'light_green' => Color::LIGHTGREEN, - 'light_magenta' => Color.web('0xffc0ff'), - 'light_red' => Color.web('0xffc0c0'), - 'light_yellow' => Color::LIGHTYELLOW, - 'magenta' => Color::MAGENTA, - 'red' => Color::RED, - 'silver' => Color::SILVER, - 'yellow' => Color::YELLOW, - 'white' => Color::WHITE, - } + 'darkyellow' => Color.web('0xc0c000'), + 'lightmagenta' => Color.web('0xffc0ff'), + 'lightred' => Color.web('0xffc0c0'), + }.merge(Color.java_class.fields.inject({}) {|final, field| + final[field.name.downcase] = field.value(nil) # TODO: what is nil supposed to be? + final + }) ## # Generate a converter for a map of supplied values. @@ -89,13 +73,12 @@ def animation_converter_for(*prop_names) # the first argument and a color coercion on the second argument. # def converter_for(method_name, *converters) - self.__send__(:define_method, method_name.to_s + - ARG_CONVERTER_SUFFIX) do |*values| + sheep = lambda do |direct, this, *values| converter = converters.find { |e| e.length == values.length } # FIXME: Better error reporting on many things which can fail i = 0 - values.inject([]) do |s, value| + values = values.inject([]) do |s, value| conv = converter[i] if conv.kind_of? Proc s << conv.call(value) @@ -105,7 +88,22 @@ def converter_for(method_name, *converters) i += 1 s end - end + if direct + return this.method("set_" + method_name.to_s).call(*values) + else + return values + end + end + # define a setter for normal usage + unless method_name == :new + self.__send__(:define_method, method_name.to_s + "=") do |*values| + sheep.call(true, self, *values) + end + end + # define a build/with usage + self.__send__(:define_method, method_name.to_s + ARG_CONVERTER_SUFFIX) do |*values| + sheep.call(false, self, *values) + end end # Map of different kinds of known converters @@ -114,7 +112,7 @@ def converter_for(method_name, *converters) value }, :color => lambda { |value| - new_value = NAME_TO_COLORS[value.to_s] + new_value = NAME_TO_COLORS[value.to_s.gsub(/_/, "")] new_value ? new_value : value }, } diff --git a/lib/jrubyfx/version.rb b/lib/jrubyfx/version.rb index 1be504b..cd69f09 100644 --- a/lib/jrubyfx/version.rb +++ b/lib/jrubyfx/version.rb @@ -1,4 +1,4 @@ module JRubyFX # Current gem version. Used in rake task. - VERSION='0.9' + VERSION='0.9.1' end diff --git a/samples/javafx/analog_clock.rb b/samples/javafx/analog_clock.rb index 55c3720..0d0a1b7 100755 --- a/samples/javafx/analog_clock.rb +++ b/samples/javafx/analog_clock.rb @@ -46,7 +46,7 @@ def start(stage) rotate end end - end.set_on_key_pressed { |e| java.lang.System.exit(0) } + end.set_on_key_pressed { |e| Platform.exit } show end play @@ -63,8 +63,8 @@ def play refresh_time # Initially set hands to proper locs handler = EventHandler.impl { |n, e| refresh_time } time = Timeline.new - time.cycleCount = Timeline::INDEFINITE - time.keyFrames << KeyFrame.new(Duration.millis(1000), handler) + time.cycle_count = :indefinite + time.keyFrames << KeyFrame.new(1000.ms, handler) time.play end end diff --git a/samples/javafx/hello_devoxx.rb b/samples/javafx/hello_devoxx.rb index aa915b7..da4f216 100755 --- a/samples/javafx/hello_devoxx.rb +++ b/samples/javafx/hello_devoxx.rb @@ -7,9 +7,15 @@ class HelloDevoxx < JRubyFX::Application def start(stage) with(stage, title: "Hello Devoxx", x: 105, y: 140) do - layout_scene(:blue) do - group do - text("Hello Devoxx", x: 105, y: 120, font: Font.new(30)) + layout_scene(500, 250, :black) do + hbox(padding: insets(60)) do + text('JRuby', font: font('sanserif', 80)) do + fill linear_gradient(0, 0, 0, 1, true, :no_cycle, [stop(0, :pale_green), stop(1, :sea_green)]) + end + text('FX', font: font('sanserif', 80)) do + fill linear_gradient(0, 0, 0, 1, true, :no_cycle, [stop(0, :cyan), stop(1, :dodger_blue)]) + set_effect(drop_shadow(color: :dodger_blue, radius: 25, spread: 0.25)) + end end end show diff --git a/samples/javafx/hello_jrubyfx.rb b/samples/javafx/hello_jrubyfx.rb index cddee66..50be6e4 100755 --- a/samples/javafx/hello_jrubyfx.rb +++ b/samples/javafx/hello_jrubyfx.rb @@ -11,8 +11,7 @@ def start(stage) layout_scene(:dark_blue) do group do rectangle(x: 10, y: 40, width: 50, height: 50, fill: :red) do - translate_x = translateXProperty - + translate_x = translateXProperty # note we must do this here as its on the rectangle, not the timeline timeline(cycle_count: :indefinite, auto_reverse: true) do animate translate_x, 0.sec => 1.sec, 0 => 200 end.play