Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating Oval to use new styles #736

Merged
merged 14 commits into from
Jun 10, 2014
4 changes: 1 addition & 3 deletions lib/shoes/arc.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
class Shoes
class Arc
include CommonMethods
include Common::Fill
include Common::Stroke
include Common::Style
include Common::Clickable
include DimensionsDelegations

attr_reader :app, :parent, :dimensions
attr_reader :app, :dimensions, :parent, :gui
style_with :angle1, :angle2, :art_styles, :center, :dimensions, :radius, :wedge
STYLES = {wedge: false}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that many of these kinds of elements can access their gui so I figured I'd add this for uniformity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the consistency of doing that. I've run into a number of cases where I had to add the gui to something just because no one had needed it quite yet.

Although I don't like meta-programming the world away, almost makes me wonder if one of our Common modules ought to just enforce that everyone gets app, parent, gui and maybe dimensions... Food for later thought.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do that. E.g. Shoes::CommonMethods or establish a base class. Something.

That wouldn't even need meta programming. You can just declare the readers in the module and bam they are there! (might be overridden in the actual class but hey no harm done!)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also: good idea!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I open an issue with this idea, or were you guys thinking to chunk that in with this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separate issue please!


Expand Down
2 changes: 0 additions & 2 deletions lib/shoes/common/style.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def style(new_styles = nil)
end

def style_init(arg_styles, new_styles = {})

default_element_styles = {}
default_element_styles = self.class::STYLES if defined? self.class::STYLES

Expand Down Expand Up @@ -63,7 +62,6 @@ def unpack_style_groups(styles)
end

def define_accessor_methods

needs_accessors = @supported_styles.reject do |style|
self.method_defined?(style)
end
Expand Down
7 changes: 4 additions & 3 deletions lib/shoes/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def sound(soundfile, opts = {}, &blk)
# @option opts [Boolean] wedge (false)
# @option opts [Boolean] center (false) is (left, top) the center of the rectangle?
def arc(left, top, width, height, angle1, angle2, opts = {})
create Shoes::Arc, left, top, width, height, angle1, angle2, opts#style.merge(arc_style)
create Shoes::Arc, left, top, width, height, angle1, angle2, opts
end

# Draws a line from point A (x1,y1) to point B (x2,y2)
Expand Down Expand Up @@ -221,7 +221,8 @@ def line(x1, y1, x2, y2, opts = {})
# @option styles [Integer] top (0) the y-coordinate of the top-left corner
# @option styles [Boolean] center (false) is (left, top) the center of the oval
def oval(*opts, &blk)
oval_style = style_normalizer.normalize pop_style(opts)
oval_style = pop_style(opts)
oval_style = style_normalizer.normalize(oval_style)
case opts.length
when 3
left, top, width = opts
Expand All @@ -243,7 +244,7 @@ def oval(*opts, &blk)
EOS
raise ArgumentError, message
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wasnotrice The merging all happens in style now, so in the dsl we don't do any merging. I'm glad you pointed this out since it was the problem! :)

create Shoes::Oval, left, top, width, height, style.merge(oval_style), &blk
create Shoes::Oval, left, top, width, height, oval_style, &blk
end

# Creates a rectangle
Expand Down
19 changes: 7 additions & 12 deletions lib/shoes/oval.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
class Shoes
class Oval
include CommonMethods
include Common::Fill
include Common::Stroke
include Common::Style
include Common::Clickable
include DimensionsDelegations

attr_reader :app, :dimensions, :angle, :gui, :parent
attr_reader :app, :dimensions, :parent, :gui
style_with :art_styles, :center, :radius

def initialize(app, parent, left, top, width, height, opts = {}, &blk)
def initialize(app, parent, left, top, width, height, styles = {}, &blk)
@app = app
@dimensions = AbsoluteDimensions.new left, top, width, height, opts
@style = Shoes::Common::Fill::DEFAULTS.merge(
Shoes::Common::Stroke::DEFAULTS).merge(opts)
@style[:strokewidth] ||= 1
@angle = opts[:angle]
@dimensions = AbsoluteDimensions.new left, top, width, height, styles
@parent = parent


style_init(styles)
@parent.add_child self

@gui = Shoes.backend_for(self, &blk)

clickable_options(opts)
clickable_options(styles)
end
end
end
18 changes: 3 additions & 15 deletions spec/shoes/arc_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,9 @@
it_behaves_like "object with style"
it_behaves_like "object with dimensions"
it_behaves_like "left, top as center", :start_angle, :end_angle
it_behaves_like 'object with parent'

#unpack styles. In the future we'd like to do something clever to avoid this duplication.
supported_styles = []
%w[art_styles cap center dimensions radius].map(&:to_sym).each do |style|
if Shoes::Common::Style::STYLE_GROUPS[style]
Shoes::Common::Style::STYLE_GROUPS[style].each{|style| supported_styles << style}
else
supported_styles << style
end
end

supported_styles.each do |style|
it_behaves_like "object that styles with #{style}"
end
it_behaves_like "object with parent"

it_styles_with :art_styles, :center, :dimensions, :radius

it "is a Shoes::Arc" do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized that this runs cap twice

expect(arc.class).to be(Shoes::Arc)
Expand Down
7 changes: 4 additions & 3 deletions spec/shoes/oval_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@

describe "basic" do
subject { Shoes::Oval.new(app, parent, left, top, width, height) }
it_behaves_like "object with stroke"
it_behaves_like "object with fill"
it_behaves_like "object with style"
it_behaves_like "object with dimensions"
it_behaves_like "movable object"
it_behaves_like "left, top as center"
it_behaves_like 'object with parent'
it_behaves_like "object with parent"

it_styles_with :art_styles, :center, :dimensions, :radius
end
end
64 changes: 46 additions & 18 deletions spec/shoes/shared_examples/dsl/oval.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,80 @@
expect(oval.width).to eq(width)
expect(oval.height).to eq(height)
end

it "sets stroke" do
expect(oval.style[:stroke]).to eq(stroke)
end

it "sets fill" do
expect(oval.style[:fill]).to eq(fill)
end
end

shared_examples_for "oval DSL method" do
let(:left) { 20 }
let(:top) { 30 }
let(:width) { 100 }
let(:height) { 200 }
let(:stroke) { Shoes::COLORS[:black] }
let(:fill) { Shoes::COLORS[:black] }

let(:oval) { dsl.oval(left, top, width, height) }
describe "creating an oval" do
describe "with explicit arguments" do
let(:oval) { dsl.oval(left, top, width, height) }
it_behaves_like "an oval/circle element"
end

context "eccentric, from explicit arguments" do
it_behaves_like "an oval/circle element"
end
describe "with stroke and fill styles" do
let(:stroke) { Shoes::COLORS.fetch :orchid }
let(:fill) { Shoes::COLORS.fetch :lemonchiffon }

it "raises an ArgumentError" do
expect { dsl.oval(10) }.to raise_error(ArgumentError)
describe "as colors" do
let(:oval) { dsl.oval(left, top, width, height, stroke: stroke, fill: fill) }
it_behaves_like "an oval/circle element"
end

describe "as hex strings" do
let(:oval) { dsl.oval(left, top, width, height, stroke: stroke.hex, fill: fill.hex) }
it_behaves_like "an oval/circle element"
end
end

describe "with too few arguments" do
it "raises an ArgumentError" do
expect { dsl.oval(10) }.to raise_error(ArgumentError)
end
end
end

context "a circle" do
describe "creating a circle" do
let(:width) { height }

describe "when constructed from explicit arguments" do
describe "with explicit arguments" do
let(:oval) { dsl.oval(left, top, width, height) }
it_behaves_like "an oval/circle element"
end

describe "when constructed with a top, left and diameter" do
let(:circle) { dsl.oval(left, top, width) }
describe "with top, left, diameter" do
let(:oval) { dsl.oval(left, top, width) }
it_behaves_like "an oval/circle element"
end

describe "when constructing from a style hash" do
describe "using left, top, height, width" do
let(:circle) { dsl.oval(left: left, top: top, width: width, height: height) }
describe "with a style hash" do
describe "containing left, top, height, width" do
let(:oval) { dsl.oval(left: left, top: top, width: width, height: height) }
it_behaves_like "an oval/circle element"
end

describe "using left, top, height, width, center: false" do
let(:circle) { dsl.oval(left: left, top: top, width: width, height: height, center: false) }
describe "containing left, top, height, width, center: false" do
let(:oval) { dsl.oval(left: left, top: top, width: width, height: height, center: false) }
it_behaves_like "an oval/circle element"
end

describe "using left, top, diameter" do
let(:circle) { dsl.oval(left: left, top: top, diameter: width) }
describe "containing left, top, diameter" do
let(:oval) { dsl.oval(left: left, top: top, diameter: width) }
it_behaves_like "an oval/circle element"
end
end
end

end
4 changes: 2 additions & 2 deletions spec/shoes/shared_examples/dsl/stroke.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@

it "applies to subsequently created objects" do
dsl.stroke color
expect(Shoes::Oval).to receive(:new) do |*args|
expect(Shoes::Rect).to receive(:new) do |*args|
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed these to Rect from oval because they were breaking. If you test the things these are supposed to test, they do work as expected but the tests fail. So we should rework the dsl stroke, strokewidth, etc tests in a different PR.

For now it works to just stick these tests on an element that doesn't use the new styling.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems totally reasonable to me. 👍

style = args.pop
expect(style[:stroke]).to eq(color)
end
dsl.oval(10, 10, 100, 100)
dsl.rect(10, 10, 100, 100)
end

context "with hex string" do
Expand Down
4 changes: 2 additions & 2 deletions spec/shoes/shared_examples/dsl/strokewidth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

it "applies to subsequently created objects" do
dsl.strokewidth 6
expect(Shoes::Oval).to receive(:new) do |*args|
expect(Shoes::Rect).to receive(:new) do |*args|
style = args.pop
expect(style[:strokewidth]).to eq(6)
end
dsl.oval(10, 10, 100, 100)
dsl.rect(10, 10, 100, 100)
end
end
23 changes: 23 additions & 0 deletions spec/shoes/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
require 'spec_helper'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, so this is the only thing I changed essentially with this last commit. Something tells me this is pretty unorthodox and therefore maybe bad, but I view it more as a quick patch until the meta-styles spec issue (the one where we don't want to use lots of it_behaves_likes) gets addressed.

Whaddya think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with pulling these out in this fashion as long as it's an interim step, which seems to be your plan.

def it_styles_with(*styles)
supported_styles = unpack_styles(styles)
spec_styles(supported_styles)
end

def unpack_styles(styles)
supported_styles = []
styles.each do |style|
if Shoes::Common::Style::STYLE_GROUPS[style]
Shoes::Common::Style::STYLE_GROUPS[style].each{|style| supported_styles << style}
else
supported_styles << style
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also extract a method maybe and indent back one level (is a follow up error of the indention error before I guess)

end
supported_styles
end

def spec_styles(supported_styles)
supported_styles.each do |style|
it_behaves_like "object that styles with #{style}"
end
end
2 changes: 1 addition & 1 deletion spec/swt_shoes/shared_examples/swt_app_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
add_paint_listener: true, remove_paint_listener: true,
add_clickable_element: true, add_listener: true,
flush: true, redraw: true) }
let(:shoes_app) { double('shoes app', gui: swt_app, rotate: 0) }
let(:shoes_app) { double('shoes app', gui: swt_app, rotate: 0, style: {}, element_styles: {}) }
let(:parent) { double('parent', app: swt_app, add_child: true, real: true) }
let(:parent_dsl) {double("parent dsl", add_child: true, contents: [],
gui: parent, x_dimension: double.as_null_object,
Expand Down
6 changes: 3 additions & 3 deletions static/manual-en.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1692,10 +1692,10 @@ also set, shapes drawn will not be visible.
Draws a line using the current line color (aka "stroke") starting at
coordinates (left, top) and ending at coordinates (x2, y2).

=== oval(left, top, radius) » Shoes::Shape ===
=== oval(left, top, diameter) » Shoes::Shape ===
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on what I saw over in #118 I changed the manual too.


Draws a circular form at pixel coordinates (left, top) with a width and height
of `radius` pixels. The line and fill colors are used to draw the shape. By
of `diameter` pixels. The line and fill colors are used to draw the shape. By
default, the coordinates are for the oval's leftmost, top corner, but this can
be changed by calling the [[Art.transform]] method or by using the `:center`
style on the next method below.
Expand All @@ -1718,7 +1718,7 @@ Draw circular form using a style hash. The following styles are supported:

* `top`: the y-coordinate for the oval pen.
* `left`: the x-coordinate for the oval pen.
* `radius`: the width and height of the circle.
* `diameter`: the width and height of the circle.
* `width`: a specific pixel width for the oval.
* `height`: a specific pixel height for the oval.
* `center`: do the coordinates specific the oval's center? (true or false)
Expand Down