Use general_no_thumbnail instead of imageviewer_no_pic if the movie has no poster
[cinaest] / src / movie-window.vala
1 /* This file is part of Cinaest.
2  *
3  * Copyright (C) 2009 Philipp Zabel
4  *
5  * Cinaest is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Cinaest is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Cinaest. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using Gtk;
20 using Hildon;
21
22 public class MovieWindow : StackableWindow {
23         private MovieMenu menu;
24         private Gdk.Pixbuf no_poster;
25         private MoviePoster.Factory poster_factory;
26         private HBox hbox;
27         private Image image;
28         private VBox details;
29         private PannableArea pannable;
30         private Label title_label;
31         private Label rating_label;
32         private Label plot;
33         private bool portrait_mode;
34
35         public MovieWindow.with_movie (Movie movie, MovieListStore store) {
36                 update_title (movie);
37
38                 // View menu
39                 menu = new MovieMenu (movie, store, this);
40
41                 set_main_menu (menu);
42
43                 // Poster
44                 image = new Image ();
45
46                 if (movie.poster != null && movie.poster.large != null) {
47                         image.pixbuf = movie.poster.large;
48                 } else {
49                         if (movie.poster != null && movie.poster.small != null) {
50                                 // FIXME
51                                 image.pixbuf = movie.poster.small.scale_simple (288, 400, Gdk.InterpType.BILINEAR);
52                         } else {
53                                 // FIXME
54                                 if (no_poster == null) try {
55                                         no_poster = new Gdk.Pixbuf.from_file ("/usr/share/icons/hicolor/64x64/hildon/general_no_thumbnail.png");
56                                 } catch (Error e) {
57                                         critical ("Missing general_no_thumbnail icon: %s\n", e.message);
58                                 }
59                                 image.pixbuf = no_poster;
60                         }
61                         try {
62                                 poster_factory = MoviePoster.Factory.get_instance ();
63                                 poster_factory.queue (movie, receive_poster);
64                         } catch (Error e) {
65                                 warning ("Failed to queue poster request: %s\n", e.message);
66                         }
67                 }
68
69                 title_label = new Label (title_label_markup (movie));
70                 title_label.wrap = true;
71                 title_label.use_markup = true;
72                 title_label.set_alignment (0.0f, 0.0f);
73
74                 var header = new HBox (false, 0);
75                 header.pack_start (title_label, true, true, 0);
76
77                 rating_label = new Label (rating_label_markup (movie));
78                 rating_label.use_markup = true;
79                 rating_label.set_alignment (0.5f, 0.0f);
80                 header.pack_start (rating_label, false, false, MARGIN_DOUBLE);
81
82                 plot = new Label (movie.get_plot ());
83                 plot.wrap = true;
84                 plot.set_alignment (0.0f, 0.0f);
85
86                 details = new VBox (false, MARGIN_DOUBLE);
87                 details.pack_start (header, false, false, 0);
88                 details.pack_start (plot, false, false, 0);
89
90                 var pannable = new PannableArea ();
91                 var eventbox = new EventBox ();
92                 eventbox.add (details);
93                 eventbox.above_child = true;
94                 pannable.add_with_viewport (eventbox);
95
96                 hbox = new HBox (false, 0);
97                 hbox.pack_start (pannable, true, true, 0);
98
99                 portrait_mode = CinaestProgram.orientation.portrait;
100                 if (portrait_mode) {
101                         details.pack_start (image, false, false, 0);
102                         details.reorder_child (image, 0);
103                         plot.set_size_request (480 - 2 * MARGIN_DOUBLE, -1);
104                 } else {
105                         hbox.pack_start (image, false, false, MARGIN_DOUBLE);
106                         hbox.reorder_child (image, 0);
107                         plot.set_size_request (800 - 288 /* image */ - 3 * MARGIN_DOUBLE, -1);
108                         pannable.set_size_request (-1, 424);
109                 }
110
111                 hbox.show_all ();
112                 add (hbox);
113
114                 // Connect signals
115                 menu.movie_deleted.connect (() => { destroy (); });
116                 Gdk.Screen.get_default ().size_changed.connect (on_orientation_changed);
117                 movie.notify.connect (this.on_movie_changed);
118         }
119
120         private void update_title (Movie movie) {
121                 Gdk.Color color;
122                 this.ensure_style ();
123                 if (this.style.lookup_color ("SecondaryTextColor", out color))
124                         set_markup ("%s <span size=\"small\" fgcolor=\"%s\">(%d)</span>".printf (movie.title, color.to_string (), movie.year));
125                 else
126                         set_markup ("%s <small>(%d)</small>".printf (movie.title, movie.year));
127         }
128
129         private string title_label_markup (Movie movie) {
130                 Gdk.Color color;
131                 this.ensure_style ();
132                 string year = "";
133                 if (this.style.lookup_color ("SecondaryTextColor", out color)) {
134                         if (movie.year > 0)
135                                 year = " <span fgcolor=\"%s\">(%d)</span>".printf (color.to_string (), movie.year);
136                         return "<big><b>%s</b></big>%s\n<span size=\"small\" fgcolor=\"%s\">%s</span>".printf (movie.title, year, color.to_string (), movie.secondary);
137                 } else {
138                         if (movie.year > 0)
139                                 year = " (%d)".printf (movie.year);
140                         return "<big><b>%s</b></big>%s\n<small>%s</small>".printf (movie.title, year, movie.secondary);
141                 }
142         }
143
144         private string rating_label_markup (Movie movie) {
145                 if (movie.rating > 0)
146                         return "<big><b>%d.%d</b></big>".printf (movie.rating / 10, movie.rating % 10);
147                 else
148                         return "";
149         }
150
151         private void receive_poster (Gdk.Pixbuf pixbuf, Movie movie) {
152                 var poster = new Poster();
153
154                 poster.large = pixbuf;
155                 if (movie.poster != null) {
156                         poster.icon = movie.poster.icon;
157                         poster.small = movie.poster.small;
158                 }
159                 movie.poster = poster;
160         }
161
162         private void on_movie_changed (GLib.Object source, GLib.ParamSpec spec) {
163                 var movie = (Movie) source;
164
165                 if ((spec.name == "title") || (spec.name == "year")) {
166                         update_title (movie);
167                         title_label.set_markup (title_label_markup (movie));
168                 }
169                 if (spec.name == "rating") {
170                         rating_label.set_markup (rating_label_markup (movie));
171                 }
172                 if ((spec.name == "poster") && (movie.poster != null) && (movie.poster.large != null)) {
173                         image.pixbuf = movie.poster.large;
174                 }
175         }
176
177         private void on_orientation_changed (Gdk.Screen screen) {
178                 if (CinaestProgram.orientation.portrait == portrait_mode)
179                         return;
180
181                 portrait_mode = CinaestProgram.orientation.portrait;
182                 if (portrait_mode) {
183                         hbox.remove (image);
184                         details.pack_start (image, false, false, 0);
185                         details.reorder_child (image, 0);
186                         plot.set_size_request (480 - 2 * MARGIN_DOUBLE, -1);
187                         pannable.set_size_request (-1, -1);
188                 } else {
189                         details.remove (image);
190                         hbox.pack_start (image, false, false, MARGIN_DOUBLE);
191                         hbox.reorder_child (image, 0);
192                         pannable.set_size_request (-1, 424);
193                         plot.set_size_request (800 - 288 /* image */ - 3 * MARGIN_DOUBLE, -1);
194                 }
195         }
196 }
197