/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * collapser.cc * * Mon Sep 15 09:48:46 CEST 2008 * Copyright 2008 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of Pracro. * * Pracro is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Pracro 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pracro; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "collapser.h" #include #include #include #include "debug.h" #define ANIM_TIME 400 // ms #define ANIM_INTERVAL 5 // ms Collapser::Collapser(QWidget *collapsed, QWidget *expanded, bool setcollapsed, QScrollArea *scrollarea) { this->collapsed = NULL; this->expanded = NULL; this->scrollarea = scrollarea; timer = new QTimer(this); timer->setSingleShot(true); timer->setInterval(ANIM_INTERVAL); connect(timer, SIGNAL(timeout()), this, SLOT(anim())); setLayout(new QHBoxLayout()); layout()->setContentsMargins(0,0,0,0); setWidgets(collapsed, expanded); is_collapsed = !setcollapsed; // Make sure setCollapsed actually does something. setCollapsed(setcollapsed); } void Collapser::updateHeight() { int c_height = 16; int e_height = 16; if(collapsed) { QSize sz = collapsed->minimumSizeHint(); c_height = sz.height(); } if(expanded) { QSize sz = expanded->minimumSizeHint(); e_height = sz.height(); } if(isCollapsed()) { setFixedHeight(c_height); } else { setFixedHeight(e_height); } } void Collapser::setWidgets(QWidget *collapsed, QWidget *expanded) { setCollapsedWidget(collapsed); setExpandedWidget(expanded); } void Collapser::setCollapsedWidget(QWidget *collapsed) { this->collapsed = collapsed; if(isCollapsed() == true && collapsed) { layout()->addWidget(collapsed); collapsed->setVisible(true); } } void Collapser::setExpandedWidget(QWidget *expanded) { this->expanded = expanded; if(isCollapsed() == false && expanded) { layout()->addWidget(expanded); expanded->setVisible(true); } } QWidget *Collapser::collapsedWidget() { return collapsed; } QWidget *Collapser::expandedWidget() { return expanded; } bool Collapser::isCollapsed() { return is_collapsed; } void Collapser::setCollapsed(bool setcollapsed) { if(this->is_collapsed == setcollapsed) return; if(setcollapsed) collapse(); else expand(); } void Collapser::collapse() { emit collapsing(); t_anim.start(); is_collapsed = true; timer->start(); if(expanded) { expanded->setVisible(false); layout()->removeWidget(expanded); } if(expanded) placeholder.grab_from(expanded); layout()->addWidget(&placeholder); placeholder.setVisible(true); if(collapsed) placeholder.grab_to(collapsed); } void Collapser::expand() { emit expanding(); t_anim.start(); // show expanded if(collapsed) { collapsed->setVisible(false); //qApp->processEvents(); // Make sure it is actually invisble before removing it form the layout. layout()->removeWidget(collapsed); placeholder.grab_from(collapsed); } layout()->addWidget(&placeholder); placeholder.setVisible(true); if(expanded) placeholder.grab_to(expanded); is_collapsed = false; timer->start(); } void Collapser::toggleCollapse() { if(!is_collapsed) collapse(); else expand(); } void Collapser::anim() { int c_height = 16; int e_height = 16; if(collapsed) { QSize sz = collapsed->minimumSizeHint(); c_height = sz.height(); } if(expanded) { QSize sz = expanded->minimumSizeHint(); e_height = sz.height(); } double x = (double)(t_anim.elapsed()) / (double)ANIM_TIME; double y = 1; if(x < 1) { y = x * x * x; placeholder.setWeight(x); int height; if(!is_collapsed) { height = (int)((1 - y) * c_height + y * e_height); } else { height = (int)((1 - y) * e_height + y * c_height); } setFixedHeight(height); timer->start(); } else { if(is_collapsed) { // show collapsed placeholder.setVisible(false); layout()->removeWidget(&placeholder); if(collapsed) { layout()->addWidget(collapsed); // collapsed->setFixedHeight(c_height); collapsed->setVisible(true); } setFixedHeight(c_height); emit doneCollapsing(); } else { setFixedHeight(e_height); placeholder.setVisible(false); layout()->removeWidget(&placeholder); if(expanded) { layout()->addWidget(expanded); expanded->setVisible(true); } emit doneExpanding(); if(scrollarea && expanded) { scrollarea->ensureWidgetVisible(expanded); } } } } void Collapser::Placeholder::paintEvent(QPaintEvent *) { QPainter p(this); p.setOpacity(1 - weight); p.drawPixmap(rect(), pixmap_from, pixmap_from.rect()); p.setOpacity(weight); p.drawPixmap(rect(), pixmap_to, pixmap_to.rect()); } void Collapser::Placeholder::grab_from(QWidget *w) { weight = 0; // Reset if(!w) return; // w->setFixedWidth(contentsRect().width()); QSize sz = w->minimumSizeHint(); // w->setFixedHeight(sz.height()); w->resize(width(), sz.height()); pixmap_from = QPixmap::grabWidget(w, 0, 0); } void Collapser::Placeholder::grab_to(QWidget *w) { weight = 0; // Reset if(!w) return; // w->setFixedWidth(contentsRect().width()); QSize sz = w->minimumSizeHint(); // w->setFixedHeight(sz.height()); w->resize(width(), sz.height()); pixmap_to = QPixmap::grabWidget(w, 0, 0); } void Collapser::Placeholder::setWeight(double w) { weight = w * w * w; }