00001 00005 /* Copyright © 2009, 2010 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 #include "Viewport.h" 00012 00013 #include <Debug.h> 00014 00015 Viewport::Viewport() 00016 : Gtk::Table(2, 2) 00017 , m_h_scroll_adjustment(49.5, 0.0, 101.0, 1.5, 1.0, 1.0) 00018 , m_h_scroll_bar(m_h_scroll_adjustment) 00019 , m_v_scroll_adjustment(49.5, 0.0, 101.0, 1.5, 1.0, 1.0) 00020 , m_v_scroll_bar(m_v_scroll_adjustment) 00021 , document(0) 00022 { 00023 create(); 00024 } 00025 00026 Viewport::Viewport(Viewport & viewport) 00027 : Gtk::Table(2, 2) 00028 , m_h_scroll_adjustment(49.5, 0.0, 101.0, 1.5, 1.0, 1.0) 00029 , m_h_scroll_bar(m_h_scroll_adjustment) 00030 , m_v_scroll_adjustment(49.5, 0.0, 101.0, 1.5, 1.0, 1.0) 00031 , m_v_scroll_bar(m_v_scroll_adjustment) 00032 , m_view(viewport.m_view) 00033 , document(viewport.document) 00034 { 00035 create(); 00036 } 00037 00038 void Viewport::create() 00039 { 00040 add_events(Gdk::SCROLL_MASK); 00041 attach(m_h_scroll_bar, 0, 1, 1, 2, 00042 Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK); 00043 m_h_scroll_bar.show(); 00044 attach(m_v_scroll_bar, 1, 2, 0, 1, 00045 Gtk::SHRINK, Gtk::FILL | Gtk::EXPAND); 00046 m_v_scroll_bar.show(); 00047 attach(m_view, 0, 1, 0, 1, 00048 Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND); 00049 m_view.show(); 00050 m_h_scroll_bar.signal_change_value().connect( 00051 sigc::mem_fun(*this, &Viewport::on_h_scrollbar_change_value)); 00052 m_v_scroll_bar.signal_change_value().connect( 00053 sigc::mem_fun(*this, &Viewport::on_v_scrollbar_change_value)); 00054 m_v_scroll_bar.set_inverted(); 00055 } 00056 00057 Viewport::~Viewport() 00058 { 00059 } 00060 00061 void Viewport::set_document(Document::Document & document_in) 00062 { 00063 document = &document_in; 00064 m_view.set_document(document_in); 00065 resize_adjustments(); 00066 } 00067 00068 void Viewport::update() 00069 { 00070 resize_adjustments(); 00071 // Redraw the view to reflect the changed track. 00072 m_view.queue_draw(); 00073 } 00074 00075 void Viewport::set_angle(const ViewAngle angle) 00076 { 00077 m_view.set_angle(angle); 00078 resize_adjustments(); 00079 } 00080 00081 void Viewport::zoom_in() 00082 { 00083 m_view.set_scale(m_view.get_scale() * 1.25); 00084 resize_adjustments(); 00085 } 00086 00087 void Viewport::zoom_out() 00088 { 00089 m_view.set_scale(m_view.get_scale() * 0.8); 00090 resize_adjustments(); 00091 } 00092 00093 void Viewport::scale_to_fit() 00094 { 00095 // find the scale to fit in each direction. 00096 float scale_x = double(m_view.get_width()) / 00097 ( m_h_scroll_adjustment.get_upper() - 00098 m_h_scroll_adjustment.get_lower()); 00099 float scale_y = double(m_view.get_height()) / 00100 ( m_v_scroll_adjustment.get_upper() - 00101 m_v_scroll_adjustment.get_lower()); 00102 // now use the largest scale so they both fit. 00103 if (scale_x < scale_y) 00104 { 00105 m_view.set_scale(scale_x); 00106 } 00107 else 00108 { 00109 m_view.set_scale(scale_y); 00110 } 00111 00112 resize_adjustments(); 00113 // move scrollbars to the middle. 00114 double lower = m_h_scroll_adjustment.get_lower(); 00115 double upper = m_h_scroll_adjustment.get_upper(); 00116 double size = m_h_scroll_adjustment.get_page_size(); 00117 double pos = lower + (upper - lower - size) / 2.0; 00118 m_h_scroll_adjustment.set_value(pos); 00119 on_h_scrollbar_change_value(Gtk::SCROLL_NONE, m_h_scroll_adjustment.get_value()); 00120 00121 lower = m_v_scroll_adjustment.get_lower(); 00122 upper = m_v_scroll_adjustment.get_upper(); 00123 size = m_v_scroll_adjustment.get_page_size(); 00124 pos = lower + (upper - lower - size) / 2.0; 00125 m_v_scroll_adjustment.set_value(pos); 00126 on_v_scrollbar_change_value(Gtk::SCROLL_NONE, m_v_scroll_adjustment.get_value()); 00127 } 00128 00129 void Viewport::resize_adjustments() 00130 { 00131 // don't adjust before a document is assigned. 00132 if (!document) 00133 { 00134 DEBUG_MESSAGE(" No track to use to set scrollbar adjustments"); 00135 return; 00136 } 00137 const Track::AxisAlignedBoundingBox box(document->get_track().get_path().get_bounding_box()); 00138 const float scale = m_view.get_scale(); 00139 // Find the half the distance across the screen. 00140 double h_offset = double(m_view.get_width()) / scale / 2.0; 00141 double v_offset = double(m_view.get_height()) / scale / 2.0; 00142 // set the page size of the adjustments to the amount shown on the screen 00143 m_h_scroll_adjustment.set_page_size(h_offset * 2.0); 00144 m_v_scroll_adjustment.set_page_size(v_offset * 2.0); 00145 // adjust step size to reflect the scale. 00146 m_h_scroll_adjustment.set_step_increment(20.0 / scale); 00147 m_v_scroll_adjustment.set_step_increment(20.0 / scale); 00148 if (box.valid()) 00149 { 00150 switch (m_view.get_angle()) 00151 { 00152 case View::VIEW_TOP: 00153 m_h_scroll_adjustment.set_lower(box.get_min_x()); 00154 m_h_scroll_adjustment.set_upper(box.get_max_x()); 00155 m_v_scroll_adjustment.set_lower(box.get_min_y()); 00156 m_v_scroll_adjustment.set_upper(box.get_max_y()); 00157 // scroll bar's value is the begining of the page, 00158 // so it is half the page size lower than the centre. 00159 m_h_scroll_adjustment.set_value(m_view.get_centre().x() - h_offset); 00160 m_v_scroll_adjustment.set_value(m_view.get_centre().y() - v_offset); 00161 break; 00162 case View::VIEW_SIDE: 00163 m_h_scroll_adjustment.set_lower(box.get_min_y()); 00164 m_h_scroll_adjustment.set_upper(box.get_max_y()); 00165 m_v_scroll_adjustment.set_lower(box.get_min_z()); 00166 m_v_scroll_adjustment.set_upper(box.get_max_z()); 00167 m_h_scroll_adjustment.set_value(m_view.get_centre().y() - h_offset); 00168 m_v_scroll_adjustment.set_value(m_view.get_centre().z() - v_offset); 00169 break; 00170 case View::VIEW_FRONT: 00171 m_h_scroll_adjustment.set_lower(box.get_min_x()); 00172 m_h_scroll_adjustment.set_upper(box.get_max_x()); 00173 m_v_scroll_adjustment.set_lower(box.get_min_z()); 00174 m_v_scroll_adjustment.set_upper(box.get_max_z()); 00175 m_h_scroll_adjustment.set_value(m_view.get_centre().x() - h_offset); 00176 m_v_scroll_adjustment.set_value(m_view.get_centre().z() - v_offset); 00177 break; 00178 } 00179 } else { 00180 m_h_scroll_adjustment.set_lower(-30.0); 00181 m_h_scroll_adjustment.set_upper(30.0); 00182 m_v_scroll_adjustment.set_lower(-30.0); 00183 m_v_scroll_adjustment.set_upper(30.0); 00184 DEBUG_MESSAGE(" No valid bounding box for track!"); 00185 } 00186 // now Update the scrollbar for the display and to emit notify signals. 00187 m_h_scroll_bar.set_adjustment(m_h_scroll_adjustment); 00188 m_v_scroll_bar.set_adjustment(m_v_scroll_adjustment); 00189 on_h_scrollbar_change_value(Gtk::SCROLL_NONE, m_h_scroll_adjustment.get_value()); 00190 on_v_scrollbar_change_value(Gtk::SCROLL_NONE, m_v_scroll_adjustment.get_value()); 00191 } 00192 00193 bool Viewport::on_h_scrollbar_change_value(Gtk::ScrollType scroll, double new_value) 00194 { 00195 DEBUG_MESSAGE("Horizontal scrollbar's value changed."); 00196 btVector3 centre = m_view.get_centre(); 00197 double h_offset = m_h_scroll_adjustment.get_page_size() / 2.0; 00198 switch (m_view.get_angle()) 00199 { 00200 case View::VIEW_TOP: 00201 // the value of the scrollbar is the position of the left edge, 00202 // so the position of the centre is half the screen width more. 00203 centre.setX(new_value + h_offset); 00204 break; 00205 case View::VIEW_SIDE: 00206 centre.setY(new_value + h_offset); 00207 break; 00208 case View::VIEW_FRONT: 00209 centre.setX(new_value + h_offset); 00210 break; 00211 } 00212 m_view.set_centre(centre); 00213 return true; 00214 } 00215 00216 bool Viewport::on_v_scrollbar_change_value(Gtk::ScrollType scroll, double new_value) 00217 { 00218 btVector3 centre = m_view.get_centre(); 00219 double v_offset = m_v_scroll_adjustment.get_page_size() / 2.0; 00220 switch (m_view.get_angle()) 00221 { 00222 case View::VIEW_TOP: 00223 centre.setY(new_value + v_offset); 00224 break; 00225 case View::VIEW_SIDE: 00226 centre.setZ(new_value + v_offset); 00227 break; 00228 case View::VIEW_FRONT: 00229 centre.setZ(new_value + v_offset); 00230 break; 00231 } 00232 m_view.set_centre(centre); 00233 return true; 00234 } 00235 00236 bool Viewport::on_scroll_event(GdkEventScroll * event) 00237 { 00238 switch (event->direction) 00239 { 00240 case GDK_SCROLL_UP: 00241 m_v_scroll_bar.set_value(m_v_scroll_bar.get_value() 00242 + m_v_scroll_adjustment.get_step_increment()); 00243 on_v_scrollbar_change_value(Gtk::SCROLL_NONE, 00244 m_v_scroll_bar.get_value()); 00245 break; 00246 case GDK_SCROLL_DOWN: 00247 m_v_scroll_bar.set_value(m_v_scroll_bar.get_value() 00248 - m_v_scroll_adjustment.get_step_increment()); 00249 on_v_scrollbar_change_value(Gtk::SCROLL_NONE, 00250 m_v_scroll_bar.get_value()); 00251 break; 00252 case GDK_SCROLL_LEFT: 00253 m_h_scroll_bar.set_value(m_h_scroll_bar.get_value() 00254 - m_h_scroll_adjustment.get_step_increment()); 00255 on_h_scrollbar_change_value(Gtk::SCROLL_NONE, 00256 m_h_scroll_bar.get_value()); 00257 break; 00258 case GDK_SCROLL_RIGHT: 00259 m_h_scroll_bar.set_value(m_h_scroll_bar.get_value() 00260 + m_h_scroll_adjustment.get_step_increment()); 00261 on_h_scrollbar_change_value(Gtk::SCROLL_NONE, 00262 m_h_scroll_bar.get_value()); 00263 break; 00264 } 00265 return true; 00266 } 00267 00268 void Viewport::realize_view() 00269 { 00270 m_view.realize(); 00271 } 00272 00273 sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > Viewport::signal_command() 00274 { 00275 return m_view.signal_command(); 00276 } 00277 00278 sigc::signal<void, boost::shared_ptr<Document::DocumentDelta> > Viewport::signal_preview_command() 00279 { 00280 return m_view.signal_preview_command(); 00281 } 00282 00283 sigc::signal<void> Viewport::signal_preview_cancel() 00284 { 00285 return m_view.signal_preview_cancel(); 00286 }
Generated at Mon Sep 6 00:41:13 2010 by Doxygen version 1.4.7 for Racer version svn335.