# Copyright 2007, 2008, 2009, 2010, 2011, 2013, 2014 Kevin Ryde
# This file is part of Chart.
#
# Chart is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3, or (at your option) any later version.
#
# Chart is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with Chart. If not, see <http://www.gnu.org/licenses/>.
package App::Chart::Gtk2::ViewStyleDialog;
use 5.010;
use strict;
use warnings;
use Glib::Ex::ConnectProperties;
use Gtk2;
use Locale::TextDomain ('App-Chart');
use App::Chart::Glib::Ex::MoreUtils;
use Gtk2::Ex::Units;
use App::Chart;
use App::Chart::Gtk2::GUI;
use App::Chart::Gtk2::View;
# uncomment this to run the ### lines
#use Smart::Comments;
use base 'App::Chart::Gtk2::Ex::ToplevelSingleton';
use Glib::Object::Subclass
'Gtk2::Dialog',
signals => { notify => \&_do_notify,
show => \&_do_show },
properties => [Glib::ParamSpec->scalar
('viewstyle',
'viewstyle',
'Blurb.',
Glib::G_PARAM_READWRITE),
Glib::ParamSpec->object
('view',
'view',
'Blurb.',
'App::Chart::Gtk2::View',
Glib::G_PARAM_READWRITE),
];
use constant RESPONSE_SAVE => 0;
sub INIT_INSTANCE {
my ($self) = @_;
$self->set_title (__('Chart: View Style'));
$self->add_buttons ('gtk-ok' => 'ok',
'gtk-save' => RESPONSE_SAVE,
'gtk-cancel' => 'cancel',
'gtk-help' => 'help');
$self->signal_connect (response => \&_do_response);
my $vbox = $self->vbox;
$vbox->pack_start (Gtk2::Label->new
("Warning, this dialog is not quite right."),
0,0,0);
my $hbox = Gtk2::HBox->new (0, 0);
$vbox->pack_start ($hbox, 0, 0, 0);
my $adjust_splits = $self->{'adjust_splits'}
= Gtk2::CheckButton->new_with_label (__('Adj splits'));
$adjust_splits->set_tooltip_text (__('Whether to adjust past prices to the current share capital basis'));
$hbox->pack_start ($adjust_splits, 0, 0, Gtk2::Ex::Units::em($hbox));
my $adjust_dividends = $self->{'adjust_dividends'}
= Gtk2::CheckButton->new_with_label (__('Adj dividends'));
$adjust_dividends->set_tooltip_text (__('Whether to adjust past prices down for dividends paid out'));
$adjust_dividends->signal_connect (toggled => \&_do_button_toggled);
$hbox->pack_start ($adjust_dividends, 0, 0, Gtk2::Ex::Units::em($hbox));
my $adjust_imputation = $self->{'adjust_imputation'}
= Gtk2::CheckButton->new_with_label (__('Adj imputation'));
$adjust_imputation->set_tooltip_text (__('Whether to adjust past prices down for any imputation credits attached to dividends (only applicable when dividend adjustments selected)'));
$adjust_imputation->signal_connect (toggled => \&_do_button_toggled);
# only applicable when divs enabled
Glib::Ex::ConnectProperties->new ([$adjust_dividends,'active'],
[$adjust_imputation,'sensitive']);
$hbox->pack_start ($adjust_imputation, 0, 0, Gtk2::Ex::Units::em($hbox));
my $adjust_rollovers = $self->{'adjust_rollovers'}
= Gtk2::CheckButton->new_with_label (__('Adj rollovers'));
$adjust_rollovers->set_tooltip_text (__('Whether to adjust past prices up for front month futures contract rollovers'));
$hbox->pack_start ($adjust_rollovers, 0, 0, Gtk2::Ex::Units::em($hbox));
$adjust_rollovers->signal_connect (toggled => \&_do_button_toggled);
my $lower_hbox = Gtk2::HBox->new;
$vbox->pack_end ($lower_hbox, 0,0,0);
$vbox->pack_end (Gtk2::HSeparator->new, 0,0,0);
my $add_graph = $self->{'add_graph'}
= Gtk2::Button->new_with_label (__('Add Graph'));
$add_graph->signal_connect (clicked => \&_do_add_graph);
$lower_hbox->pack_start ($add_graph, 0,0,0);
$self->set_viewstyle (App::Chart::Gtk2::View::DEFAULT_VIEWSTYLE);
$vbox->show_all;
}
sub GET_PROPERTY {
my ($self, $pspec) = @_;
my $pname = $pspec->get_name;
if ($pspec->get_name eq 'viewstyle') {
return $self->get_viewstyle;
} else {
return $self->{$pname};
}
}
sub SET_PROPERTY {
my ($self, $pspec, $newval) = @_;
my $pname = $pspec->get_name;
if ($pname eq 'viewstyle') {
$self->set_viewstyle ($newval);
} else {
$self->{$pname} = $newval;
}
}
sub get_viewstyle {
my ($self) = @_;
my $vbox = $self->vbox;
return { adjust_splits => $self->{'adjust_splits'}->get_active,
adjust_dividends => $self->{'adjust_dividends'}->get_active,
adjust_imputation => $self->{'adjust_imputation'}->get_active,
adjust_rollovers => $self->{'adjust_rollovers'}->get_active,
graphs => [ map { $_->isa('App::Chart::Gtk2::GraphStyleWidget')
? ($_->get_graphstyle)
: () }
$vbox->get_children ]
};
}
sub set_viewstyle {
my ($self, $viewstyle) = @_;
### ViewStyleDialog set_viewstyle(): $viewstyle
require Glib::Ex::FreezeNotify;
my $freezer = Glib::Ex::FreezeNotify->new ($self);
foreach my $field (qw(adjust_splits adjust_dividends adjust_imputation
adjust_rollovers)) {
$self->{$field}->set_active ($viewstyle->{$field})
}
my $vbox = $self->vbox;
my @graphs = grep {$_->isa('App::Chart::Gtk2::GraphStyleWidget')}
$vbox->get_children;
my $graphstyles = ($viewstyle->{'graphs'} ||= []);
while (@graphs > @$graphstyles) {
$vbox->remove (pop @graphs);
}
foreach my $i (0 .. $#$graphstyles) {
if (my $graph = $graphs[$i]) {
$graph->set_graphstyle ($graphstyles->[$i]);
} else {
my $graph = $graphs[$i] = App::Chart::Gtk2::GraphStyleWidget->new
(graphstyle => $graphstyles->[$i]);
$graph->signal_connect (notify => \&_do_graphstyle_notify);
$graph->signal_connect (delete_graph => \&_do_graphstyle_delete);
$vbox->pack_start ($graph, 0,0,
0.25 * Gtk2::Ex::Units::line_height($self));
}
$graphs[$i]->{'i'} = $i;
}
$vbox->show_all;
$self->notify ('viewstyle');
}
sub _do_button_toggled {
my ($origin) = @_;
my $self = $origin->get_ancestor(__PACKAGE__);
### ViewStyleDialog _do_button_toggled(): $origin
$self->notify ('viewstyle');
}
sub _do_response {
my ($self, $response) = @_;
if ($response eq RESPONSE_SAVE) {
$self->save;
} elsif ($response eq 'ok') {
$self->save;
$self->hide;
} elsif ($response eq 'cancel') {
$self->hide;
} elsif ($response eq 'help') {
require App::Chart::Manual;
App::Chart::Manual->open(__p('manual-node','View Style'), $self);
}
}
# 'show' class closure
sub _do_show {
my ($self) = @_;
$self->load;
return shift->signal_chain_from_overridden(@_);
}
sub load {
my ($self) = @_;
require App::Chart::Gtk2::View;
$self->set_viewstyle (App::Chart::Gtk2::View::viewstyle_read());
}
sub save {
my ($self) = @_;
require App::Chart::Gtk2::View;
App::Chart::Gtk2::View::viewstyle_write ($self->get_viewstyle);
}
# 'notify' signal class closure
sub _do_notify {
my ($self, $pspec) = @_;
$self->signal_chain_from_overridden ($pspec);
if ($pspec->get_name eq 'viewstyle') {
if (my $view = $self->{'view'}) {
$view->set (viewstyle => $self->get_viewstyle);
}
}
}
sub _do_graphstyle_notify {
my ($graphstylewidget, $pspec) = @_;
my $self = $graphstylewidget->get_ancestor(__PACKAGE__) || return;
if ($pspec->get_name eq 'graphstyle') {
### ViewStyleDialog _do_graphstyle_notify() change
$self->notify ('viewstyle');
}
}
sub _do_add_graph {
my ($button) = @_;
my $self = $button->get_ancestor(__PACKAGE__);
my $viewstyle = $self->get_viewstyle;
push @{$viewstyle->{'graphs'}}, { size => 1,
indicators => [{ key => 'None' }],
};
$self->set_viewstyle ($viewstyle);
}
sub _do_graphstyle_delete {
my ($graphstylewidget) = @_;
my $self = $graphstylewidget->get_ancestor(__PACKAGE__) || return;
my $i = $graphstylewidget->{'i'};
my $viewstyle = $self->get_viewstyle;
my $graphstyles = $viewstyle->{'graphs'};
splice @$graphstyles, $i,1;
$self->set_viewstyle ($viewstyle);
}
package App::Chart::Gtk2::GraphStyleWidget;
use strict;
use warnings;
use Gtk2;
use Locale::TextDomain ('App-Chart');
use App::Chart;
use App::Chart::Gtk2::GUI;
use Glib::Object::Subclass
'Gtk2::VBox',
properties => [Glib::ParamSpec->scalar
('graphstyle',
'graphstyle',
'Blurb.',
Glib::G_PARAM_READWRITE),
],
signals => { delete_graph => { param_types => [],
return_type => undef,
flags => ['action'] },
};
sub INIT_INSTANCE {
my ($self) = @_;
$self->pack_start (Gtk2::HSeparator->new, 0,0,0);
my $hbox = $self->{'hbox'} = Gtk2::HBox->new (0, 0);
$self->pack_start ($hbox, 0,0,0);
my $label = Gtk2::Label->new (__('Graph') . ' ');
$hbox->pack_start ($label, 0,0,0);
my $spin_label = Gtk2::Label->new (__('Size'));
$hbox->pack_start ($spin_label, 0,0,0);
my $size_adj = $self->{'size_adj'}
= Gtk2::Adjustment->new (1, # initial
1, 999, # min,max
1,10, # steps
0); # page_size
$size_adj->signal_connect (value_changed => \&_do_size_adj_changed,
App::Chart::Glib::Ex::MoreUtils::ref_weak($self));
my $size_spin = Gtk2::SpinButton->new ($size_adj, 10, 0);
$size_spin->set_tooltip_text
(__('The size of this graph, relative to the others'));
$hbox->pack_start ($size_spin, 0,0,0);
my $delete_button = Gtk2::Button->new_with_label (__('Delete Graph'));
$hbox->pack_end ($delete_button, 0,0,0);
$delete_button->signal_connect (clicked => \&_do_delete_graph);
my $add_button = Gtk2::Button->new_with_label (__('Add Indicator'));
$hbox->pack_end ($add_button, 0,0,0);
$add_button->signal_connect (clicked => \&_do_add_indicator);
}
sub GET_PROPERTY {
my ($self, $pspec) = @_;
my $pname = $pspec->get_name;
if ($pspec->get_name eq 'graphstyle') {
return $self->get_graphstyle;
} else {
return $self->{$pname};
}
}
sub SET_PROPERTY {
my ($self, $pspec, $newval) = @_;
my $pname = $pspec->get_name;
if ($pspec->get_name eq 'graphstyle') {
$self->set_graphstyle ($newval);
} else {
$self->{$pname} = $newval;
}
}
sub get_graphstyle {
my ($self) = @_;
my $graphstyle = { size => $self->{'size_adj'}->value,
indicators => [ map {$_->get('indicatorstyle')}
$self->indicatorstylewidgets ],
};
my $linestyle = ($self->{'linestylecombo'}
&& $self->{'linestylecombo'}->get('linestyle'));
if (defined $linestyle) {
$graphstyle->{'linestyle'} = $linestyle;
}
return $graphstyle;
}
sub set_graphstyle {
my ($self, $graphstyle) = @_;
$self->{'size_adj'}->set_value ($graphstyle->{'size'} // 1);
my $linestyle = $graphstyle->{'linestyle'};
if (defined $linestyle) {
require App::Chart::Gtk2::LineStyleComboBox;
my $linestylecombo = ($self->{'linestylecombo'} ||= do {
my $combo = App::Chart::Gtk2::LineStyleComboBox->new (visible => 1);
$combo->signal_connect (changed => \&_do_linestyle_combo_changed);
my $hbox = $self->{'hbox'};
$hbox->pack_start ($combo, 0,0, Gtk2::Ex::Units::em($combo));
$hbox->reorder_child ($combo, 3);
$combo;
});
$linestylecombo->set(linestyle => $linestyle);
} else {
delete $self->{'linestylecombo'};
}
my $indicators = $graphstyle->{'indicators'};
my @indicatorwidgets = $self->indicatorstylewidgets;
while (@indicatorwidgets > @$indicators) {
$self->remove (pop @indicatorwidgets);
}
for (my $i = 0; $i < @$indicators; $i++) {
my $indicatorstylewidget = $indicatorwidgets[$i] || do {
my $w = App::Chart::IndicatorStyleWidget->new
(visible => 1,
type => (defined $linestyle ? 'average' : 'indicator'));
$w->signal_connect ('notify::indicatorstyle',
\&_do_indicatorstyle_notify, $i);
$self->pack_start ($w, 0,0,0);
$w;
};
$indicatorstylewidget->set (indicatorstyle => $indicators->[$i])
}
### indicatorstylewidgets: join(' ',$self->indicatorstylewidgets)
}
sub _do_size_adj_changed {
my ($adj, $ref_weak_self) = @_;
my $self = $$ref_weak_self || return;
### GraphStyleWidget _do_size_adj_changed()
$self->notify ('graphstyle');
}
sub _do_linestyle_combo_changed {
my ($combo) = @_;
my $self = $combo->get_ancestor (__PACKAGE__);
### GraphStyleWidget _do_linestyle_combo_changed(): "$combo"
$self->notify ('graphstyle');
}
sub _do_add_indicator {
my ($button) = @_;
my $self = $button->get_ancestor(__PACKAGE__) || return;
### GraphStyleWidget _do_add_indicator()
my $graphstyle = $self->get_graphstyle;
push @{$graphstyle->{'indicators'}}, { key => 'None',
ma_days => 20,
};
### GraphStyleWidget _do_add_indicator(): $graphstyle
$self->set_graphstyle ($graphstyle);
}
sub _do_delete_graph {
my ($button) = @_;
my $self = $button->get_ancestor(__PACKAGE__) || return;
### GraphStyleWidget _do_delete_graph()
$self->signal_emit('delete_graph');
}
sub indicatorstylewidgets {
my ($self) = @_;
return grep {$_->isa('App::Chart::IndicatorStyleWidget')} $self->get_children;
}
sub _do_indicatorstyle_notify {
my ($indicatorstylewidget, $pspec, $n) = @_;
my $self = $indicatorstylewidget->get_ancestor(__PACKAGE__) || return;
### GraphStyleWidget _do_indicatorstyle_notify()
my $graphstyle = $self->get_graphstyle;
$graphstyle->{'indicators'}->[$n]
= $indicatorstylewidget->get('indicatorstyle');
$self->notify ('graphstyle');
}
package App::Chart::IndicatorStyleWidget;
use strict;
use warnings;
use Gtk2;
use Locale::TextDomain ('App-Chart');
use App::Chart;
use App::Chart::Gtk2::GUI;
use App::Chart::IndicatorInfo;
use Glib::Object::Subclass
'Gtk2::VBox',
properties => [ Glib::ParamSpec->scalar
('indicatorstyle',
'indicatorstyle',
'Blurb.',
Glib::G_PARAM_READWRITE),
Glib::ParamSpec->string
('type',
'type',
'Indicator type either "indicator" or "average".',
'',
Glib::G_PARAM_READWRITE),
];
sub INIT_INSTANCE {
my ($self) = @_;
my $hbox = Gtk2::HBox->new;
$self->pack_start ($hbox, 0,0,0);
require App::Chart::Gtk2::IndicatorComboBox;
my $combo = $self->{'combo'} = App::Chart::Gtk2::IndicatorComboBox->new;
$combo->signal_connect (changed => \&_do_combo_changed);
$hbox->pack_start ($combo, 0,0,0);
my $info_button = $self->{'info_button'}
= Gtk2::Button->new_from_stock ('gtk-info');
$info_button->signal_connect (clicked => \&_do_info_button);
$hbox->pack_end ($info_button, 0,0,0);
# my $delete_button = $self->{'delete_button'}
# = Gtk2::Button->new_from_stock ('gtk-delete');
# $delete_button->signal_connect (clicked => \&_do_delete_button);
# $hbox->pack_end ($delete_button, 0,0,0);
my $parambox = $self->{'parambox'} = Gtk2::HBox->new;
$parambox->show;
$self->pack_start ($parambox, 0,0,0);
$parambox->pack_start (Gtk2::Label->new(' '), 0,0,0);
$hbox->show_all;
$parambox->show_all;
}
sub SET_PROPERTY {
my ($self, $pspec, $newval) = @_;
my $pname = $pspec->get_name;
$self->{$pname} = $newval;
if ($pname eq 'indicatorstyle') {
my $indicatorstyle = $newval;
$self->{'combo'}->set_key ($indicatorstyle->{'key'});
$self->{'indicatorstyle'} = { %$newval }; # copy
} elsif ($pname eq 'type') {
$self->{'combo'}->set (type => $newval);
}
}
sub _do_info_button {
my ($info_button) = @_;
# supposed to be insensitive when no manual, but check just in case
my $manual = $info_button->{'manual'} || return;
my $self = $info_button->get_ancestor(__PACKAGE__) || return;
require App::Chart::Manual;
App::Chart::Manual->open ($manual, $self);
}
sub _update_info_tooltip {
my ($self) = @_;
my $info_button = $self->{'info_button'};
my $manual = $info_button->{'manual'} = $self->indicator_info->manual;
$info_button->set_tooltip_text
($manual ? __x('Open the manual at the section "{section}"',
section => $manual)
: undef);
$info_button->set_sensitive ($manual);
}
sub _do_delete_button {
# my ($delete_button) = @_;
# my $self = $delete_button->get_ancestor(__PACKAGE__) || return;
print "Can't delete indicator yet\n";
}
sub _update_params {
my ($self) = @_;
my $indicatorstyle = $self->{'indicatorstyle'};
my $parameter_info = $self->indicator_info->parameter_info;
my $parambox = $self->{'parambox'};
my @paramwidgets = $parambox->get_children;
shift @paramwidgets; # not the spacer
while (@paramwidgets > @$parameter_info) {
$parambox->remove (pop @paramwidgets);
}
local $self->{'update_in_progress'} = 1;
for (my $i = 0; $i < @$parameter_info; $i++) {
my $paramwidget = ($paramwidgets[$i] || do {
my $pp = App::Chart::IndicatorParamWidget->new (visible => 1);
$pp->signal_connect ('notify::paramvalue' => \&_do_paramvalue_changed, $i);
$parambox->pack_start ($pp, 0,0,0);
$pp;
});
my $paramkey = $parameter_info->[$i]->{'key'};
my $paramvalue = ($indicatorstyle->{$paramkey}
// $parameter_info->[$i]->{'default'});
require Glib::Ex::FreezeNotify;
my $freezer = Glib::Ex::FreezeNotify->new ($paramwidget);
$paramwidget->set (paraminfo => $parameter_info->[$i],
paramvalue => $paramvalue);
}
}
# return a App::Chart::IndicatorInfo
sub indicator_info {
my ($self) = @_;
my $indicatorstyle = $self->{'indicatorstyle'};
return App::Chart::IndicatorInfo->new ($indicatorstyle->{'key'});
}
sub _do_combo_changed {
my ($combo) = @_;
my $self = $combo->get_ancestor(__PACKAGE__) || return;
my $indicatorstyle = $self->{'indicatorstyle'};
$indicatorstyle->{'key'} = $self->{'combo'}->get('key');
_update_info_tooltip ($self);
_update_params ($self);
$self->notify ('indicatorstyle');
}
sub _do_paramvalue_changed {
my ($paramwidget, $pspec, $n) = @_;
### IndicatorStyleWidget _do_paramvalue_changed()
my $self = $paramwidget->get_ancestor(__PACKAGE__) || return;
my $parameter_info = $self->indicator_info->parameter_info;
my $indicatorstyle = $self->{'indicatorstyle'};
my $param_key = $parameter_info->[$n]->{'key'};
my $paramvalue = $paramwidget->get('paramvalue');
if ($paramvalue == $parameter_info->[$n]->{'default'}) {
delete $indicatorstyle->{$param_key};
} else {
$indicatorstyle->{$param_key} = $paramwidget->get('paramvalue');
}
### indicatorstyle: $self->get('indicatorstyle')
if (! $self->{'update_in_progress'}) {
$self->notify('indicatorstyle');
}
}
package App::Chart::IndicatorParamWidget;
use 5.010;
use strict;
use warnings;
use Carp;
use Gtk2;
use POSIX ();
use Locale::TextDomain ('App-Chart');
use App::Chart;
use App::Chart::Gtk2::GUI;
use App::Chart::IndicatorInfo;
use Glib::Object::Subclass
'Gtk2::HBox',
properties => [ Glib::ParamSpec->scalar
('paraminfo',
'paraminfo',
'Blurb.',
Glib::G_PARAM_READWRITE),
Glib::ParamSpec->scalar
('paramvalue',
'paramvalue',
'Blurb.',
Glib::G_PARAM_READWRITE),
];
sub INIT_INSTANCE {
my ($self) = @_;
my $label = $self->{'label'} = Gtk2::Label->new ('');
$self->pack_start ($label, 0,0,0);
my $adj = $self->{'adj'}
= Gtk2::Adjustment->new (1, # initial
1, 9999, # min,max
1,10, # steps
0); # page_size
$adj->signal_connect (value_changed => \&_do_adj_value_changed,
App::Chart::Glib::Ex::MoreUtils::ref_weak($self));
}
sub SET_PROPERTY {
my ($self, $pspec, $newval) = @_;
my $pname = $pspec->get_name;
$self->{$pname} = $newval;
### IndicatorParamWidget SET_PROPERTY: $pname, $newval
if ($pname eq 'paramvalue') {
my $paraminfo = $self->{'paraminfo'} // return;
my $type = $paraminfo->{'type'} // 'integer';
if ($type eq 'boolean') {
$self->{'child'}->set_active ($newval);
} else {
$self->{'child'}->set_value ($newval);
}
} elsif ($pname eq 'paraminfo') {
my $paraminfo = $self->{'paraminfo'};
if ($paraminfo) {
if (my $child = delete $self->{'child'}) {
$self->remove ($child);
}
my $type = $paraminfo->{'type'} // 'integer';
if ($type eq 'boolean') {
my $check = $self->{'child'} = Gtk2::CheckButton->new;
$check->signal_connect ('notify::active',
\&_do_checkbutton_changed);
$self->pack_start ($check, 0,0,0);
} else {
# 'integer' or 'float'
my $step = $paraminfo->{'step'} // 1;
$self->{'adj'}->set
(lower => $paraminfo->{'minimum'} // 0,
upper => $paraminfo->{'maximum'} // POSIX::FLT_MAX(),
page_increment => $step,
step_increment => $step,
page_size => 0);
$self->{'adj'}->changed;
my $spin = $self->{'child'}
= Glib::Object::new ('Gtk2::SpinButton',
adjustment => $self->{'adj'},
climb_rate => $step,
digits => ($paraminfo->{'decimals'}
// ($type eq 'float' ? 1 : 0)),
xalign => 1.0);
$self->pack_start ($spin, 0,0,0);
}
$self->{'child'}->show;
$self->{'label'}->set_text ($paraminfo->{'name'} . ' ');
}
}
}
sub _do_adj_value_changed {
my ($adj, $ref_weak_self) = @_;
my $self = $$ref_weak_self || return;
$self->{'paramvalue'} = $adj->value;
$self->notify('paramvalue');
}
sub _do_checkbutton_changed {
my ($check) = @_;
my $self = $check->get_ancestor(__PACKAGE__) || return;
$self->{'paramvalue'} = $check->get_active;
$self->notify('paramvalue');
}
1;
__END__
# =head1 NAME
#
# App::Chart::Gtk2::ViewStyleDialog -- view style dialog widget
#
# =head1 SYNOPSIS
#
# use App::Chart::Gtk2::ViewStyleDialog;
# my $dialog = App::Chart::Gtk2::ViewStyleDialog->instance;
# $dialog->present;
#
# =head1 WIDGET HIERARCHY
#
# C<App::Chart::Gtk2::ViewStyleDialog> is a subclass of C<Gtk2::Dialog>.
#
# Gtk2::Widget
# Gtk2::Container
# Gtk2::Bin
# Gtk2::Window
# Gtk2::Dialog
# App::Chart::Gtk2::ViewStyleDialog
#
# =head1 DESCRIPTION
#
# ...
#
# =cut