📄 region.cpp
字号:
// This file is part of Ambulant Player, www.ambulantplayer.org.//// Copyright (C) 2003-2007 Stichting CWI, // Kruislaan 413, 1098 SJ Amsterdam, The Netherlands.//// Ambulant Player is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published by// the Free Software Foundation; either version 2.1 of the License, or// (at your option) any later version.//// Ambulant Player 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 Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public License// along with Ambulant Player; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA/* * @$Id: region.cpp,v 1.109 2007/02/12 14:14:47 jackjansen Exp $ */#include "ambulant/lib/logger.h"#include "ambulant/common/region.h"#include "ambulant/common/preferences.h"//#define AM_DBG#ifndef AM_DBG#define AM_DBG if(0)#endifusing namespace ambulant;using namespace common;using namespace lib;// Factoriescommon::surface_factory *common::create_smil_surface_factory(){ return new smil_surface_factory();}common::surface_template *smil_surface_factory::new_topsurface( const common::region_info *info, common::bgrenderer *bgrend, common::window_factory *wf){ lib::size bounds; if (info) { rect rect = info->get_rect(); bounds = lib::size(rect.width(), rect.height()); } else { // XXX This is not the correct place to get the default size, as // any subregion calculation (percentage values, regPoint/regAlign) // will not take the value into account. Should be done in the // smil_layout_manager. bounds = wf->get_default_size(); } return new toplevel_surface_impl(info, bounds, bgrend, wf);}surface_impl::surface_impl(const std::string &name, surface_impl *parent, rect bounds, const region_info *info, bgrenderer *bgrenderer): m_name(name), m_bounds_inited(false), m_highlighting(false), m_inner_bounds(bounds.innercoordinates(bounds)), m_outer_bounds(bounds), m_window_topleft(bounds.left_top()), m_parent(parent), m_info(info),// m_alignment(NULL), m_bg_renderer(bgrenderer), m_renderer_data(NULL), m_renderer_id(NULL){ if (parent) m_window_topleft += parent->get_global_topleft(); if (m_bg_renderer) { m_bg_renderer->set_surface(this); } if (!m_info) lib::logger::get_logger()->debug("surface_impl(): m_info==NULL for \"%s\"", name.c_str());}surface_impl::~surface_impl(){ AM_DBG lib::logger::get_logger()->debug("~surface_impl(0x%x)", (void*)this); m_parent = NULL; std::list<gui_events*>::reverse_iterator ari; for(ari=m_renderers.rbegin(); ari!=m_renderers.rend(); ari++) { delete (*ari); } if (m_bg_renderer) delete m_bg_renderer; m_bg_renderer = NULL; if (m_renderer_data) m_renderer_data->release(); m_renderer_data = NULL;// if (m_info)// delete m_info; for(children_map_t::iterator it1=m_active_children.begin();it1!=m_active_children.end();it1++) { children_list_t& cl = (*it1).second; for(children_list_t::iterator it2=cl.begin();it2!=cl.end();it2++) delete (*it2); }}common::surface_template *surface_impl::new_subsurface(const region_info *info, bgrenderer *bgrenderer){ rect bounds = info->get_rect(); zindex_t z = info->get_zindex(); AM_DBG lib::logger::get_logger()->debug("subbregion %s: ltrb=(%d, %d, %d, %d), z=%d", info->get_name().c_str(), bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), z); surface_impl *rv = new surface_impl(info->get_name(), this, bounds, info, bgrenderer); AM_DBG lib::logger::get_logger()->debug("subbregion: returning 0x%x", (void*)rv); m_children_cs.enter(); m_active_children[zindex_t(z)].push_back(rv); m_children_cs.leave(); need_redraw(bounds); return rv;}common::surface *surface_impl::activate(){ return this;}voidsurface_impl::animated(){ AM_DBG lib::logger::get_logger()->debug("surface_impl::animated(%s, 0x%x)", m_name.c_str(), (void*)this); clear_cache();// XXX: Temporary: What should be redrawn is the union of the area before and after#ifndef AMBULANT_PLATFORM_WIN32 need_redraw(m_inner_bounds);#else m_parent->need_redraw();#endif}voidsurface_impl::show(gui_events *cur){ m_children_cs.enter();#if 1 // Sanity check: it shouldn't be in here already std::list<gui_events*>::iterator i; for(i=m_renderers.begin(); i!=m_renderers.end(); i++) assert((*i) != cur);#endif m_renderers.push_back(cur); m_children_cs.leave(); AM_DBG lib::logger::get_logger()->debug("surface_impl[0x%x].show(0x%x)", (void *)this, (void *)cur); if(m_parent) { m_parent->add_subregion(m_info->get_zindex(), this); } need_redraw();}voidsurface_impl::renderer_done(gui_events *cur){ AM_DBG lib::logger::get_logger()->debug("surface_impl[0x%x].renderer_done(0x%x)", (void *)this, (void*)cur); m_children_cs.enter(); std::list<gui_events*>::iterator i = m_renderers.end(); for(i=m_renderers.begin(); i!=m_renderers.end(); i++) if ((*i) == cur) break; if (i == m_renderers.end()) { lib::logger::get_logger()->trace("surface_impl[0x%x].renderer_done(0x%x): not found in %d active renderers!", (void *)this, (void*)cur, m_renderers.size()); } else { m_renderers.erase(i); } m_children_cs.leave(); if(m_parent) { m_parent->del_subregion(m_info->get_zindex(), this); } need_redraw(m_inner_bounds);}voidsurface_impl::keep_as_background(){ if (m_info->is_subregion()) m_parent->keep_as_background(); else if (m_bg_renderer) m_bg_renderer->keep_as_background();}voidsurface_impl::redraw(const lib::rect &r, gui_window *window){ AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s, ltrb=(%d, %d, %d, %d))", (void *)this, m_name.c_str(), r.left(), r.top(), r.right(), r.bottom()); rect our_outer_rect = r & m_outer_bounds; rect our_rect = m_outer_bounds.innercoordinates(our_outer_rect); if (our_rect.empty()) { AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s) returning: nothing to draw", (void *)this, m_name.c_str()); return; } // For now: if we are going to redraw anything we have to redraw everything (sigh). our_rect = m_inner_bounds; //////////////// // Draw the content of this AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s, our_ltrb=(%d, %d, %d, %d)) ->draw_background", (void *)this, m_name.c_str(), our_rect.left(), our_rect.top(), our_rect.right(), our_rect.bottom()); // First the background draw_background(our_rect, window); // Then the active renderers // For the win32 arrangement we should have at most one active m_children_cs.enter(); //XXX Why is this assertion needed ? //assert(m_renderers.size()<=1); std::list<gui_events*>::iterator ar; for (ar=m_renderers.begin(); ar!=m_renderers.end(); ar++) { AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s) ->renderer 0x%x", (void *)this, m_name.c_str(), (void *)(*ar)); (*ar)->redraw(our_rect, window); } // Draw active subregions in reverse activation order and in the correct z-order for(children_map_t::iterator it1=m_subregions.begin();it1!=m_subregions.end();it1++) { children_list_t& cl = (*it1).second; for(children_list_t::iterator it2=cl.begin();it2!=cl.end();it2++) { AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s) ->subregion 0x%x", (void *)this, m_name.c_str(), (void *)(*it2)); if (!(*it2)->get_info()->is_subregion()) { AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x): subregion 0x%x is not a subregion", (void*)this, (void*)(*it2)); //(*it2)->redraw(our_rect, window); } (*it2)->redraw(our_rect, window); } } // Then the children regions of this // XXXX Should go per z-order value for(children_map_t::iterator it2=m_active_children.begin();it2!=m_active_children.end();it2++) { AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s) examining next z-order list", (void*)this, m_name.c_str()); children_list_t& cl = (*it2).second; for(children_list_t::iterator it3=cl.begin();it3!=cl.end();it3++) { if(!(*it3)->get_info()->is_subregion()) { AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s) -> child 0x%x", (void *)this, m_name.c_str(), (void *)(*it3)); (*it3)->redraw(our_rect, window); } } } // Finally any highlighting needed if (m_highlighting && m_bg_renderer) m_bg_renderer->highlight(window); AM_DBG lib::logger::get_logger()->debug("surface_impl.redraw(0x%x %s) returning", (void*)this, m_name.c_str()); m_children_cs.leave();}voidsurface_impl::draw_background(const lib::rect &r, gui_window *window){ // Now we should make sure we have a background renderer if (!m_bg_renderer) { AM_DBG lib::logger::get_logger()->debug("draw_background %s: no m_bg_renderer", m_name.c_str()); return; } AM_DBG lib::logger::get_logger()->debug("draw_background(0x%x %s): drawing background", (void*)this, m_name.c_str()); m_bg_renderer->redraw(r, window);}voidsurface_impl::user_event(const lib::point &where, int what){ AM_DBG lib::logger::get_logger()->debug("surface_impl.user_event(0x%x, (%d, %d))", (void *)this, where.x, where.y); // Test that it is in our area if (!m_outer_bounds.contains(where)) { AM_DBG lib::logger::get_logger()->debug("surface_impl.user_event: not in our bounds"); return; } // Convert to local coordinates point our_point = where; our_point -= m_outer_bounds.left_top(); std::list<gui_events*>::reverse_iterator ari; m_children_cs.enter(); for (ari=m_renderers.rbegin(); ari!=m_renderers.rend(); ari++) { AM_DBG lib::logger::get_logger()->debug("surface_impl.user_event(0x%x) ->active 0x%x", (void *)this, (void *)(*ari)); (*ari)->user_event(our_point, what); } children_map_t::reverse_iterator it1; for(it1=m_active_children.rbegin();it1!=m_active_children.rend();it1++) { children_list_t& cl = (*it1).second; children_list_t::iterator it2; for(it2=cl.begin();it2!=cl.end();it2++) { AM_DBG lib::logger::get_logger()->debug("surface_impl.user_event(0x%x) -> child 0x%x,z=%d", (void *)this, (void *)(*it2), (*it1).first); (*it2)->user_event(our_point, what); } } m_children_cs.leave();}voidsurface_impl::need_redraw(const lib::rect &r){ AM_DBG lib::logger::get_logger()->debug("surface_impl[0x%x].need_redraw(xywh=%d,%d,%d,%d)", (void*)this, r.left(), r.top(), r.width(), r.height()); if (!m_parent) return; // Audio region or some such rect parent_rect = r & m_inner_bounds; m_parent->need_redraw(m_outer_bounds.outercoordinates(parent_rect));}voidsurface_impl::need_redraw(){ need_redraw(m_inner_bounds);}voidsurface_impl::need_events(bool want){ if (!m_parent) return; // Audio region or some such // Not good enough: we only forward that we want events if (want) m_parent->need_events(want);}const lib::point &surface_impl::get_global_topleft() const{ const_cast<surface_impl*>(this)->need_bounds(); return m_window_topleft;}const lib::rect&surface_impl::get_clipped_screen_rect() const{ const_cast<surface_impl*>(this)->need_bounds(); return m_clipped_screen_bounds;} voidsurface_impl::need_bounds(){ if (m_bounds_inited) return; AM_DBG lib::logger::get_logger()->debug("surface_impl::need_bounds(%s, 0x%x)", m_name.c_str(), (void*)this); if (m_info) m_outer_bounds = m_info->get_rect(); AM_DBG lib::logger::get_logger()->debug("surface_impl::need_bounds: %d %d %d %d", m_outer_bounds.left(), m_outer_bounds.top(), m_outer_bounds.right(), m_outer_bounds.bottom()); m_inner_bounds = m_outer_bounds.innercoordinates(m_outer_bounds); m_window_topleft = m_outer_bounds.left_top(); if (m_parent) { m_parent->need_bounds(); m_window_topleft += m_parent->get_global_topleft(); } m_clipped_screen_bounds = m_inner_bounds; m_clipped_screen_bounds.translate(m_window_topleft); if (m_parent) { // need_bounds already called m_clipped_screen_bounds = m_clipped_screen_bounds & m_parent->m_clipped_screen_bounds; } m_bounds_inited = true;}voidsurface_impl::clear_cache(){ AM_DBG lib::logger::get_logger()->debug("surface_impl::clear_cache(%s, 0x%x)", m_name.c_str(), (void*)this); m_bounds_inited = false; // Better be safe than sorry: clear caches for all child regions m_children_cs.enter(); for(children_map_t::iterator it1=m_active_children.begin();it1!=m_active_children.end();it1++) { children_list_t& cl = (*it1).second;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -