File Coverage

blib/lib/Tk/Dressing.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Tk::Dressing;
2            
3 1     1   20708 use warnings;
  1         3  
  1         39  
4 1     1   6 use strict;
  1         2  
  1         37  
5 1     1   6 use Carp;
  1         5  
  1         114  
6            
7             #==================================================================
8             # $Author : Djibril Ousmanou $
9             # $Copyright : 2011 $
10             # $Update : 01/01/2011 00:00:00 $
11             # $AIM : Set a design for a Tk widget and its children $
12             #==================================================================
13            
14 1     1   549 use Tk;
  0            
  0            
15             use Config::Std { def_gap => 0 };
16             use File::Basename qw/ dirname /;
17             use File::Copy qw / copy /;
18             use File::Spec;
19            
20             use vars qw($VERSION);
21             $VERSION = '1.04';
22            
23             # get theme directory
24             my $themes_directory = File::Spec->catfile( dirname( $INC{'Tk/Dressing.pm'} ), 'DressingThemes' );
25            
26             my %new_theme;
27             my %initial_theme;
28             my $current_theme;
29             my $POINT = q{.};
30            
31             sub new {
32             my ($self) = @_;
33            
34             $self = ref($self) || $self;
35             my $this = {};
36             bless $this, $self;
37            
38             return $this;
39             }
40            
41             sub get_current_theme {
42             my $this = shift;
43            
44             return $current_theme;
45             }
46            
47             sub get_all_theme {
48             my $this = shift;
49            
50             opendir my $fh_rep, $themes_directory or croak "Unable to read themes directory : $themes_directory\n";
51             my @alltheme = grep {m/\.ini$/msx} readdir $fh_rep;
52             foreach (@alltheme) { s/\.ini$//msx; }
53             closedir $fh_rep or croak "Unable to close themes directory\n";
54            
55             # New themes loaded
56             push @alltheme, keys %new_theme;
57            
58             my %unique;
59             @unique{@alltheme} = ();
60            
61             return keys %unique;
62             }
63            
64             sub get_default_theme_file {
65             my ( $this, $theme, $directory ) = @_;
66            
67             if ( not defined $theme ) {
68             carp("Theme not defined\n");
69             return;
70             }
71            
72             $directory = defined $directory ? $directory : $POINT;
73            
74             my $theme_file = "$themes_directory/$theme.ini";
75             my $new_theme_file = "$directory/$theme.ini";
76            
77             # default theme file
78             if ( -e $theme_file ) {
79             copy( $theme_file, $new_theme_file );
80             return $new_theme_file;
81             }
82             carp("$theme not found\n");
83            
84             return;
85             }
86            
87             sub load_theme_file {
88             my ( $this, $theme, $theme_file ) = @_;
89            
90             if ( -e $theme_file ) {
91             read_config $theme_file => my %config;
92             $new_theme{$theme} = \%config;
93             return;
94             }
95            
96             carp("$theme_file not found\n");
97             return;
98             }
99            
100             sub clear {
101             my ( $this, $widget ) = @_;
102            
103             if ( ( not defined $widget ) or ( !Exists $widget) ) {
104             carp("Widget not defined\n");
105             return;
106             }
107            
108             if (%initial_theme) {
109             $this->design_widget( -widget => $widget, -clear => 1 );
110             $current_theme = undef;
111             }
112            
113             return 1;
114             }
115            
116             sub _default_config {
117             my ( $this, $widget, $ref_config_theme ) = @_;
118            
119             my ( $class, $type ) = split m/::/msx, ref $widget;
120             $type = defined $type ? $type : $class;
121             if ( not defined $type ) { return; }
122            
123             # Store the initial configuration before set the first theme
124             if ( !$initial_theme{$type} ) {
125             foreach my $option ( sort keys %{ $ref_config_theme->{$type} } ) {
126             my $initial_value = $widget->cget($option);
127             next if ( not defined $initial_value );
128            
129             if ( $initial_value eq 'SystemButtonFace' and $type eq 'Entry' ) {
130             if ( $option eq '-background' ) { $initial_value = 'white'; }
131             }
132             elsif ( $initial_value eq 'SystemWindow' and $type eq 'Frame' ) {
133             $initial_value = 'SystemButtonFace';
134             }
135             $initial_theme{$type}{$option} = $initial_value;
136             }
137             }
138            
139             # children widgets design setting
140             foreach my $child_level1 ( sort $widget->children ) {
141             $this->_default_config( $child_level1, $ref_config_theme );
142             }
143             return;
144             }
145            
146             #============================================
147             # set design in widget and its children
148             #============================================
149             sub design_widget {
150             my ( $this, %information ) = @_;
151            
152             my $theme = $information{-theme} || 'djibel';
153             if ( not defined $theme ) {
154             carp("Theme not defined\n");
155             return;
156             }
157            
158             my $widget = $information{-widget};
159             if ( ( not defined $widget ) or ( !Exists $widget ) ) {
160             carp("Widget not defined\n");
161             return;
162             }
163            
164             my $clear = $information{-clear};
165            
166             # Get theme configuration
167             my $ref_config_theme;
168            
169             # Clear
170             if ( defined $clear and $clear == 1 ) {
171             $ref_config_theme = \%initial_theme;
172             }
173             elsif ( exists $new_theme{$theme} ) {
174             $ref_config_theme = $new_theme{$theme};
175             }
176             else {
177             my $theme_file = "$themes_directory/$theme.ini";
178             if ( !-e $theme_file ) {
179             carp("$theme not found\n");
180             return;
181             }
182            
183             read_config $theme_file => my %config;
184             $new_theme{$theme} = \%config;
185             $ref_config_theme = $new_theme{$theme};
186             }
187             if ( not defined $ref_config_theme ) { return; }
188            
189             # Get Default configuration
190             if ( ( !%initial_theme ) or ( not defined $clear or $clear != 1 ) ) {
191             $this->_default_config( $widget, $ref_config_theme );
192             }
193            
194             # Get Class an type of widget to design it
195             my ( $class, $type ) = split m/::/msx, ref $widget;
196            
197             # For MainWindows widget, ref($widget) = MainWindow, then $type = $class
198             # Else for Tk::Widget, ref($widget) = Tk::Toplevel or Tk::Frame, etc => $type ok
199             $type = defined $type ? $type : $class;
200             if ( not defined $type ) { return; }
201            
202             # Read configuration option
203             if ( my $design_type = $ref_config_theme->{$type} ) {
204            
205             # Set configuration
206             $widget->configure( %{$design_type} );
207             }
208            
209             # children widgets design setting
210             foreach my $child_level1 ( $widget->children ) {
211             if ( defined $clear and $clear == 1 ) {
212             $this->design_widget( -widget => $child_level1, -clear => 1 );
213             }
214             else {
215             $this->design_widget( -widget => $child_level1, -theme => $theme );
216             }
217             }
218            
219             $current_theme = $theme;
220             return;
221             }
222            
223             1;
224             __END__