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

Tk canvas backend #58

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,69 @@ Name of output file in case of wanting to write to file.
```
export GKS_FILEPATH="hello.png"
```

# Tk Canvas backend notes

Tk is a multiplatform GUI toolkit that works with Ruby, in addition to
TCL, Python and Perl.

Tk allows to create multiplatform GUI applications that need little or
no code changes to run in UNIX, macOS and Windows.

You can learn more about using Tk with Ruby in
[TkDocs](https://tkdocs.com).

If you want to have a more modern way of interacting with Tk from
Ruby, you can use
[TkComponent](https://github.com/josepegea/tk_component) and
[TkInspect](https://github.com/josepegea/tk_inspect).

## Installing Tk

The `Gemfile` includes the `tk` gem inside an `optional` group, in
order to not force users not interested in TkCanvas to deal with the
installation of Tk.

If you do want to use TkCanvas while developing this gem, you'll need
to run `bundle install` specifying the `tk_canvas` group explicitly:

```ruby
bundle install --with tk_canvas
```

In addition to install the `tk` gem in your project, you need to
install the Tcl/Tk runtime in your system. The instructions depending
on the OS but it is a safe bet to install the Community Edition of
Active Tcl from https://www.activestate.com/

You have more details about installing Tk in different systems in the
excelent [TkDocs](https://tkdocs.com/tutorial/install.html) website.

## Units

Given that this backend only works with screen output, all measures
are interpreted as pixels.

## Limitations of Tk

Some rendering features of ruby_plot are not available in Tk. When
those are used, the results are downgraded as gracefully as possible.

Right now these are the unsuported features:

- Opacity: Tk doesn't support opacity. It does support "stipple" which
is a set of different density fill patterns, that don't completely
overwrite the background. TkCanvas tries to adapt the required
opacity to the nearest stipple for the closest result. Take into
account, though, that not all Tk implementations support
stipple. For instance, macOS implementations ignore it and always
use 100% opacity.

- Marker types: Tk doesn't support all the marker types defined in
ruby_plot. They could be generated manually, but right now only
those that are a 1-to-1 match are implemented.

## Testing

Given that this backend doesn't generate image files and are meant to
generate interactive images, the current tests don't apply.
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ group :test do
gem 'rake'
gem 'rspec'
end

group :tk_canvas, optional: true do
gem 'tk'
end
52 changes: 51 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,26 @@ An advanced plotting library for Ruby.

It aims to allow you to visualize anything, anywhere with a flexible, extensible, Ruby-like API.

# Usage
# Backends

Rubyplot can use different backends to render its plots:

- `magick` Using ImageMagick
- `gr` Using the GR framework
- `tk_canvas` Interactive drawing in a Canvas object using Ruby/Tk

Call `Rubyplot.set_backend` at the start of your program to select
the desired backend.

Pick the desired one:

``` ruby
Rubyplot.set_backend(:magick)
Rubyplot.set_backend(:gr)
Rubyplot.set_backend(:tk_canvas)
```

# Installing GR

Install the GR framework from the [website](https://gr-framework.org/c.html).

Expand All @@ -17,6 +36,37 @@ export GKS_FONTPATH="/home/sameer/Downloads/gr"
export RUBYPLOT_BACKEND="GR"
```

# Installing Tk

This gem is not including `tk` in its dependencies so you don't have
to install it if you're not going to use the `tk_canvas` backend.

If you will need to use this backend, you will need to add a reference
to `tk` in your `Gemfile` in addition to referring to `rubyplot`.

``` ruby
gem 'tk'
```

Running `bundle install` after this change will install it.

In addition to install the `tk` gem in your project, you need to
install the Tcl/Tk runtime in your system. The instructions depending
on the OS but it is a safe bet to install the Community Edition of
Active Tcl from https://www.activestate.com/

You have more details about installing Tk in different systems in the
excelent [TkDocs](https://tkdocs.com/tutorial/install.html) website.

If you want to have a more modern way of interacting with Tk from
Ruby, you can use
[TkComponent](https://github.com/josepegea/tk_component) and
[TkInspect](https://github.com/josepegea/tk_inspect).

# Examples

See the [examples](./examples) to see some how-to code.

# Short term priorities

Check milestones in GitHub for more information.
Expand Down
9 changes: 9 additions & 0 deletions examples/tk_canvas_wrapper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Examples using TkCanvasWrapper

Some example figures, extracted from the Tutorial, drawn in windows
using the TkCanvasWrapper.

## Running

bundle exec tk_plot_demo.rb

26 changes: 26 additions & 0 deletions examples/tk_canvas_wrapper/plot_window_raw_tk.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Minimal method to show a window with the figure using raw Tk
#
def plot_window(root = false)
figure = Rubyplot::Artist::Figure.new(height: 20, width: 20)

window = root ?
TkRoot.new { title "Plot Demo" } :
TkToplevel.new { title "Plot Demo" }
content = Tk::Tile::Frame.new(window).grid(sticky: 'nsew', column: 1, row: 1)
TkGrid.columnconfigure window, 1, weight: 1
TkGrid.rowconfigure window, 1, weight: 1
canvas = TkCanvas.new(content) { width 600; height 600 }
canvas.grid sticky: 'nwes', column: 1, row: 1
refresh_button = Tk::Tile::Button.new(content) do
text "Refresh!"
command { Tk.update; figure.show(canvas) }
end.grid(column: 1, row: 2, sticky: 'es')
TkGrid.columnconfigure content, 1, weight: 1
TkGrid.rowconfigure content, 1, weight: 1
TkGrid.rowconfigure content, 2, weight: 0

yield figure

Tk.update
figure.show(canvas)
end
33 changes: 33 additions & 0 deletions examples/tk_canvas_wrapper/plot_window_tk_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Minimal method to show a window with the figure using TkComponent
require "tk_component"

class PlotComponent < TkComponent::Base
attr_accessor :chart

def initialize(options = {})
super
@chart = options[:chart]
end

def render(p, parent_component)
p.vframe(sticky: 'wens', x_flex: 1, y_flex: 1) do |vf|
@canvas = vf.canvas(sticky: 'wens', width: 600, height: 600, x_flex: 1, y_flex: 1)
vf.button(text: "Redraw", sticky: 'e', on_click: ->(e) { chart.show(@canvas.native_item) })
end
end

def component_did_build
Tk.update
chart.show(@canvas.native_item)
end
end

def plot_window(root = false)
window = TkComponent::Window.new(title: "Plot Demo", root: root)
figure = Rubyplot::Artist::Figure.new(height: 20, width: 20)

yield figure

component = PlotComponent.new(chart: figure)
window.place_root_component(component)
end
Loading