mirror of https://github.com/CGAL/cgal
572 lines
14 KiB
C++
572 lines
14 KiB
C++
// Copyright (c) 2002-2004 INRIA Sophia-Antipolis (France).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); 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; version 2.1 of the License.
|
|
// See the file LICENSE.LGPL distributed with CGAL.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
//
|
|
//
|
|
// Author(s) : Laurent Rineau and Radu Ursu
|
|
|
|
#include <CGAL/basic.h>
|
|
|
|
|
|
#include <CGAL/Bbox_2.h>
|
|
|
|
#include <CGAL/IO/Qt_widget.h>
|
|
#include <CGAL/IO/Qt_widget_layer.h>
|
|
|
|
namespace CGAL {
|
|
|
|
Qt_widget::Qt_widget(QWidget *parent, const char *name) :
|
|
QWidget(parent, name), set_scales_to_be_done(false), Locked(0),
|
|
_pointSize(4), _pointStyle(DISC)
|
|
{
|
|
setCaption("CGAL::Qt_widget");
|
|
|
|
// initialize ranges and scales
|
|
xmin_old = xmin = -1;
|
|
xmax_old = xmax = 1;
|
|
ymin_old = ymin = -1;
|
|
ymax_old = ymax = 1;
|
|
constranges=false;
|
|
set_scales();
|
|
emit(rangesChanged());
|
|
|
|
// initialize the pixmap and the painter
|
|
painter = new QPainter;
|
|
printer = new QPrinter;
|
|
pixmap = new QPixmap;
|
|
matrix = new QWMatrix;
|
|
|
|
pixmap->resize(size());
|
|
painter->begin(pixmap);
|
|
painter->setWorldMatrix(*matrix);
|
|
|
|
// set properties
|
|
painter->setRasterOp(CopyROP);
|
|
setBackgroundColor(Qt::white);
|
|
painter->setPen(QPen(Qt::black,2));
|
|
|
|
clear();
|
|
}
|
|
|
|
void Qt_widget::set_scales()
|
|
{
|
|
if( ! isVisible() )
|
|
{
|
|
set_scales_to_be_done = true;
|
|
return;
|
|
};
|
|
set_scales_to_be_done = false;
|
|
|
|
if(!constranges)
|
|
{
|
|
xscal = yscal = min( width() / (xmax - xmin),
|
|
height() / (ymax - ymin) );
|
|
double xcenter = xmin + (xmax - xmin) / 2;
|
|
double ycenter = ymin + (ymax - ymin) / 2;
|
|
|
|
if(xscal<1) {
|
|
// if xscal < 1, width()/xscal > width(). then we can round it
|
|
// with loosing precision.
|
|
xmin = xcenter - (int)(width()/xscal)/2;
|
|
xmax = xcenter + (int)(width()/xscal)/2;
|
|
ymin = ycenter - (int)(height()/yscal)/2;
|
|
ymax = ycenter + (int)(height()/yscal)/2;
|
|
} else {
|
|
xmin = xcenter - (width()/xscal)/2;
|
|
xmax = xcenter + (width()/xscal)/2;
|
|
ymin = ycenter - (height()/yscal)/2;
|
|
ymax = ycenter + (height()/yscal)/2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xscal=width()/(xmax-xmin);
|
|
yscal=height()/(ymax-ymin);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::move_center(const double distx, const double disty)
|
|
{
|
|
xmin += distx; xmin_old += distx;
|
|
xmax += distx; xmax_old += distx;
|
|
ymin += disty; ymin_old += disty;
|
|
ymax += disty; ymax_old += disty;
|
|
redraw();
|
|
emit(rangesChanged());
|
|
}
|
|
void Qt_widget::set_center(const double x, const double y)
|
|
{
|
|
if (set_scales_to_be_done) return;
|
|
|
|
if(xscal<1) {
|
|
xmin = x - (int)(width()/xscal)/2;
|
|
xmax = x + (int)(width()/xscal)/2;
|
|
ymin = y - (int)(height()/yscal)/2;
|
|
ymax = y + (int)(height()/yscal)/2;
|
|
} else {
|
|
xmin = x - (width()/xscal)/2;
|
|
xmax = x + (width()/xscal)/2;
|
|
ymin = y - (height()/yscal)/2;
|
|
ymax = y + (height()/yscal)/2;
|
|
}
|
|
xmin_old = xmin;
|
|
xmax_old = xmax;
|
|
ymin_old = ymin;
|
|
ymax_old = ymax;
|
|
redraw();
|
|
emit(rangesChanged());
|
|
}
|
|
|
|
void Qt_widget::resize_pixmap()
|
|
{
|
|
// save paint state
|
|
QFont f=painter->font();
|
|
QBrush b=painter->brush();
|
|
QPen p=painter->pen();
|
|
QColor bc=painter->backgroundColor();
|
|
QWMatrix bm = painter->worldMatrix();
|
|
|
|
painter->end(); // end painting on pixmap
|
|
pixmap->resize(size());
|
|
painter->begin(pixmap); // begin again painting on pixmap
|
|
clear();
|
|
|
|
// restore paint state
|
|
painter->setFont(f);
|
|
painter->setBrush(b);
|
|
painter->setPen(p);
|
|
painter->setBackgroundColor(bc);
|
|
painter->setWorldMatrix(bm);
|
|
}
|
|
|
|
void Qt_widget::resizeEvent(QResizeEvent*)
|
|
{
|
|
resize_pixmap();
|
|
xmin = xmin_old;
|
|
xmax = xmax_old;
|
|
ymin = ymin_old;
|
|
ymax = ymax_old;
|
|
set_scales();
|
|
redraw();
|
|
}
|
|
|
|
void Qt_widget::showEvent(QShowEvent* e)
|
|
{
|
|
if( set_scales_to_be_done )
|
|
set_scales();
|
|
|
|
return QWidget::showEvent(e);
|
|
}
|
|
|
|
void Qt_widget::paintEvent(QPaintEvent*)
|
|
{
|
|
// save paint state
|
|
QFont f=painter->font();
|
|
QBrush b=painter->brush();
|
|
QPen p=painter->pen();
|
|
QColor bc=painter->backgroundColor();
|
|
QWMatrix bm = painter->worldMatrix();
|
|
|
|
painter->end(); // end painting on pixmap
|
|
bitBlt(this, 0, 0, pixmap); // copy pixmap to the Qt_widget
|
|
painter->begin(pixmap); // begin again painting on pixmap
|
|
painter->setWorldMatrix(bm);
|
|
|
|
// restore paint state
|
|
painter->setFont(f);
|
|
painter->setBrush(b);
|
|
painter->setPen(p);
|
|
painter->setBackgroundColor(bc);
|
|
}
|
|
|
|
void Qt_widget::mousePressEvent(QMouseEvent *e)
|
|
{
|
|
emit(s_mousePressEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mousePressEvent(e);
|
|
}
|
|
if(is_standard_active()){
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mousePressEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::mouseReleaseEvent(QMouseEvent *e)
|
|
{
|
|
emit(s_mouseReleaseEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mouseReleaseEvent(e);
|
|
}
|
|
if(is_standard_active()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mouseReleaseEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::mouseMoveEvent(QMouseEvent *e)
|
|
{
|
|
emit(s_mouseMoveEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mouseMoveEvent(e);
|
|
}
|
|
if(is_standard_active()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mouseMoveEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::wheelEvent(QWheelEvent *e)
|
|
{
|
|
emit(s_wheelEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->wheelEvent(e);
|
|
}
|
|
if(is_standard_active()){
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->wheelEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::mouseDoubleClickEvent(QMouseEvent *e)
|
|
{
|
|
emit(s_mouseDoubleClickEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mouseDoubleClickEvent(e);
|
|
}
|
|
if(is_standard_active()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->mouseDoubleClickEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::keyPressEvent(QKeyEvent *e)
|
|
{
|
|
emit(s_keyPressEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->keyPressEvent(e);
|
|
}
|
|
if(is_standard_active()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->keyPressEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::keyReleaseEvent(QKeyEvent *e)
|
|
{
|
|
emit(s_keyReleaseEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->keyReleaseEvent(e);
|
|
}
|
|
if(is_standard_active()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->keyReleaseEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::enterEvent(QEvent *e)
|
|
{
|
|
emit(s_enterEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->enterEvent(e);
|
|
}
|
|
if(is_standard_active()){
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->enterEvent(e);
|
|
}
|
|
}
|
|
|
|
void Qt_widget::leaveEvent(QEvent *e)
|
|
{
|
|
emit(s_leaveEvent(e));
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->leaveEvent(e);
|
|
}
|
|
if(is_standard_active()){
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->leaveEvent(e);
|
|
}
|
|
}
|
|
|
|
bool Qt_widget::event(QEvent *e)
|
|
{
|
|
emit(s_event(e));
|
|
QWidget::event(e);
|
|
if(!does_standard_eat_events()) {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->event(e);
|
|
}
|
|
if(is_standard_active()){
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->event(e);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Qt_widget::set_window(const double x_min, const double x_max,
|
|
const double y_min, const double y_max,
|
|
bool const_ranges)
|
|
{
|
|
xmin_old = xmin = x_min;
|
|
xmax_old = xmax = x_max;
|
|
ymin_old = ymin = y_min;
|
|
ymax_old = ymax = y_max;
|
|
constranges = const_ranges;
|
|
set_scales();
|
|
redraw();
|
|
emit(rangesChanged());
|
|
}
|
|
|
|
|
|
void Qt_widget::zoom(double ratio, double xc, double yc)
|
|
{
|
|
xscal = xscal*ratio; yscal = yscal*ratio;
|
|
set_center(xc, yc);
|
|
}
|
|
|
|
void Qt_widget::zoom(double ratio)
|
|
{
|
|
zoom(ratio,
|
|
xmin + (xmax - xmin) / 2 ,
|
|
ymin + (ymax - ymin) / 2 );
|
|
}
|
|
|
|
double Qt_widget::x_real(int x) const
|
|
{
|
|
if(xscal<1)
|
|
return(xmin+(int)(x/xscal));
|
|
else
|
|
return (xmin+x/xscal);
|
|
}
|
|
|
|
double Qt_widget::y_real(int y) const
|
|
{
|
|
if(yscal<1)
|
|
return(ymax-(int)(y/yscal));
|
|
else
|
|
return (ymax-y/yscal);
|
|
}
|
|
|
|
|
|
|
|
double Qt_widget::x_real_dist(double d) const
|
|
{
|
|
return(d/xscal);
|
|
}
|
|
|
|
double Qt_widget::y_real_dist(double d) const
|
|
{
|
|
return(d/yscal);
|
|
}
|
|
|
|
int Qt_widget::x_pixel(double x) const
|
|
{
|
|
return( static_cast<int>((x-xmin)*xscal) );
|
|
}
|
|
|
|
int Qt_widget::y_pixel(double y) const
|
|
{
|
|
return( - static_cast<int>((y-ymax)*yscal) );
|
|
}
|
|
|
|
int Qt_widget::x_pixel_dist(double d) const
|
|
{
|
|
if (d>0)
|
|
return( static_cast<int>(d*xscal) );
|
|
else
|
|
return( static_cast<int>(d*xscal) );
|
|
}
|
|
|
|
int Qt_widget::y_pixel_dist(double d) const
|
|
{
|
|
if (d>0)
|
|
return( static_cast<int>(d*yscal) );
|
|
else
|
|
return( static_cast<int>(d*yscal) );
|
|
}
|
|
|
|
Qt_widget& Qt_widget::operator<<(const Color& c)
|
|
{
|
|
setColor(CGAL2Qt_Color(c));
|
|
return *this;
|
|
}
|
|
|
|
Qt_widget& Qt_widget::operator<<(const PointStyle& ps)
|
|
{
|
|
setPointStyle(ps);
|
|
return *this;
|
|
}
|
|
|
|
void Qt_widget::clear() {
|
|
painter->eraseRect(rect());
|
|
}
|
|
|
|
Qt_widget& operator<<(Qt_widget& w, const Bbox_2& r)
|
|
{
|
|
int
|
|
xmin = w.x_pixel(r.xmin()),
|
|
ymin = w.y_pixel(r.ymin()),
|
|
xmax = w.x_pixel(r.xmax()),
|
|
ymax = w.y_pixel(r.ymax());
|
|
|
|
w.get_painter().drawWinFocusRect(xmin, ymin, xmax-xmin, ymax-ymin);
|
|
w.do_paint();
|
|
return w;
|
|
}
|
|
|
|
void Qt_widget::attach(Qt_widget_layer *layer) {
|
|
qt_layers.push_back(layer);
|
|
layer->attach(this);
|
|
layer->activate();
|
|
}
|
|
|
|
void Qt_widget::attach_standard(Qt_widget_layer *layer) {
|
|
qt_standard_layers.push_back(layer);
|
|
layer->attach(this);
|
|
layer->activate();
|
|
layer->does_eat_events = true;
|
|
}
|
|
|
|
bool Qt_widget::is_standard_active() {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool Qt_widget::does_standard_eat_events() {
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
if((*it)->does_eat_events == true)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void Qt_widget::print_to_ps(){
|
|
if(printer->setup(this)){
|
|
QPainter *ptemp = new QPainter();
|
|
ptemp = painter;
|
|
QPainter *painter_for_printer = new QPainter(printer);
|
|
painter = painter_for_printer;
|
|
painter->setClipping(true);
|
|
painter->setClipRect(rect());
|
|
lock();
|
|
emit(redraw_on_back());
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->draw();
|
|
emit(custom_redraw()); //deprecated, should use the following:
|
|
emit(redraw_on_front());
|
|
unlock();
|
|
delete painter;
|
|
painter = ptemp;
|
|
}
|
|
}
|
|
|
|
void Qt_widget::redraw()
|
|
{
|
|
if(isVisible())
|
|
{
|
|
clear();
|
|
lock();
|
|
emit(redraw_on_back());
|
|
std::list<Qt_widget_layer*>::iterator it;
|
|
for(it = qt_layers.begin(); it!= qt_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->draw();
|
|
for(it = qt_standard_layers.begin();
|
|
it!= qt_standard_layers.end(); it++)
|
|
if((*it)->is_active())
|
|
(*it)->draw();
|
|
emit(custom_redraw()); //deprecated, should use the following:
|
|
emit(redraw_on_front());
|
|
unlock();
|
|
}
|
|
};
|
|
|
|
void Qt_widget::detach(Qt_widget_layer* s)
|
|
{
|
|
qt_layers.erase(std::find(qt_layers.begin(),qt_layers.end(),s));
|
|
}
|
|
|
|
} // namespace CGAL
|
|
|
|
// moc_source_file: ../../include/CGAL/IO/Qt_widget.h
|
|
#include "Qt_widget.moc"
|