changeset 43:78515b1e29eb

* Rejig project file a bit to do pkg-config detection &c and change some HAVE_* symbol names accordingly * Add selection move/resize/delete * First stubs for add layer / pane commands
author Chris Cannam
date Wed, 01 Mar 2006 18:13:01 +0000
parents 1bdf285c4eac
children ad214997dddb
files layer/NoteLayer.cpp layer/NoteLayer.h layer/SpectrogramLayer.cpp layer/TextLayer.cpp layer/TextLayer.h layer/TimeInstantLayer.cpp layer/TimeInstantLayer.h layer/TimeValueLayer.cpp layer/TimeValueLayer.h widgets/LayerTree.cpp widgets/LayerTree.h widgets/Pane.cpp widgets/PaneStack.h
diffstat 13 files changed, 572 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/layer/NoteLayer.cpp	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/NoteLayer.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -617,6 +617,66 @@
     m_editing = false;
 }
 
+void
+NoteLayer::moveSelection(Selection s, size_t newStartFrame)
+{
+    NoteModel::EditCommand *command =
+	new NoteModel::EditCommand(m_model, tr("Drag Selection"));
+
+    NoteModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    for (NoteModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+	    NoteModel::Point newPoint(*i);
+	    newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
+void
+NoteLayer::resizeSelection(Selection s, Selection newSize)
+{
+    NoteModel::EditCommand *command =
+	new NoteModel::EditCommand(m_model, tr("Resize Selection"));
+
+    NoteModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    double ratio =
+	double(newSize.getEndFrame() - newSize.getStartFrame()) /
+	double(s.getEndFrame() - s.getStartFrame());
+
+    for (NoteModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+
+	    double targetStart = i->frame;
+	    targetStart = newSize.getStartFrame() + 
+		double(targetStart - s.getStartFrame()) * ratio;
+
+	    double targetEnd = i->frame + i->duration;
+	    targetEnd = newSize.getStartFrame() +
+		double(targetEnd - s.getStartFrame()) * ratio;
+
+	    NoteModel::Point newPoint(*i);
+	    newPoint.frame = lrint(targetStart);
+	    newPoint.duration = lrint(targetEnd - targetStart);
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
 QString
 NoteLayer::toXmlString(QString indent, QString extraAttributes) const
 {
--- a/layer/NoteLayer.h	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/NoteLayer.h	Wed Mar 01 18:13:01 2006 +0000
@@ -42,6 +42,9 @@
     virtual void editDrag(QMouseEvent *);
     virtual void editEnd(QMouseEvent *);
 
+    virtual void moveSelection(Selection s, size_t newStartFrame);
+    virtual void resizeSelection(Selection s, Selection newSize);
+
     virtual const Model *getModel() const { return m_model; }
     void setModel(NoteModel *model);
 
--- a/layer/SpectrogramLayer.cpp	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/SpectrogramLayer.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -1327,7 +1327,7 @@
 
 	    m_layer.m_cache->resize(width, height);
 	    m_layer.setCacheColourmap();
-	    m_layer.m_cache->reset();
+//!!!	    m_layer.m_cache->reset();
 
 	    // We don't need a lock when writing to or reading from
 	    // the pixels in the cache.  We do need to ensure we have
@@ -2165,6 +2165,18 @@
     if (haveValues) {
 	float dbMin = AudioLevel::multiplier_to_dB(magMin);
 	float dbMax = AudioLevel::multiplier_to_dB(magMax);
+	QString dbMinString;
+	QString dbMaxString;
+	if (dbMin == AudioLevel::DB_FLOOR) {
+	    dbMinString = tr("-Inf");
+	} else {
+	    dbMinString = QString("%1").arg(lrintf(dbMin));
+	}
+	if (dbMax == AudioLevel::DB_FLOOR) {
+	    dbMaxString = tr("-Inf");
+	} else {
+	    dbMaxString = QString("%1").arg(lrintf(dbMax));
+	}
 	if (lrintf(dbMin) != lrintf(dbMax)) {
 	    text += tr("dB:\t%1 - %2").arg(lrintf(dbMin)).arg(lrintf(dbMax));
 	} else {
--- a/layer/TextLayer.cpp	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/TextLayer.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -589,6 +589,61 @@
     }
 }    
 
+void
+TextLayer::moveSelection(Selection s, size_t newStartFrame)
+{
+    TextModel::EditCommand *command =
+	new TextModel::EditCommand(m_model, tr("Drag Selection"));
+
+    TextModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    for (TextModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+	    TextModel::Point newPoint(*i);
+	    newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
+void
+TextLayer::resizeSelection(Selection s, Selection newSize)
+{
+    TextModel::EditCommand *command =
+	new TextModel::EditCommand(m_model, tr("Resize Selection"));
+
+    TextModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    double ratio =
+	double(newSize.getEndFrame() - newSize.getStartFrame()) /
+	double(s.getEndFrame() - s.getStartFrame());
+
+    for (TextModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+
+	    double target = i->frame;
+	    target = newSize.getStartFrame() + 
+		double(target - s.getStartFrame()) * ratio;
+
+	    TextModel::Point newPoint(*i);
+	    newPoint.frame = lrint(target);
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
 QString
 TextLayer::toXmlString(QString indent, QString extraAttributes) const
 {
--- a/layer/TextLayer.h	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/TextLayer.h	Wed Mar 01 18:13:01 2006 +0000
@@ -42,6 +42,9 @@
     virtual void editDrag(QMouseEvent *);
     virtual void editEnd(QMouseEvent *);
 
+    virtual void moveSelection(Selection s, size_t newStartFrame);
+    virtual void resizeSelection(Selection s, Selection newSize);
+
     virtual void editOpen(QMouseEvent *); // on double-click
 
     virtual const Model *getModel() const { return m_model; }
--- a/layer/TimeInstantLayer.cpp	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/TimeInstantLayer.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -572,6 +572,82 @@
     m_editing = false;
 }
 
+void
+TimeInstantLayer::moveSelection(Selection s, size_t newStartFrame)
+{
+    SparseOneDimensionalModel::EditCommand *command =
+	new SparseOneDimensionalModel::EditCommand(m_model,
+						   tr("Drag Selection"));
+
+    SparseOneDimensionalModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+	    SparseOneDimensionalModel::Point newPoint(*i);
+	    newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
+void
+TimeInstantLayer::resizeSelection(Selection s, Selection newSize)
+{
+    SparseOneDimensionalModel::EditCommand *command =
+	new SparseOneDimensionalModel::EditCommand(m_model,
+						   tr("Resize Selection"));
+
+    SparseOneDimensionalModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    double ratio =
+	double(newSize.getEndFrame() - newSize.getStartFrame()) /
+	double(s.getEndFrame() - s.getStartFrame());
+
+    for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+
+	    double target = i->frame;
+	    target = newSize.getStartFrame() + 
+		double(target - s.getStartFrame()) * ratio;
+
+	    SparseOneDimensionalModel::Point newPoint(*i);
+	    newPoint.frame = lrint(target);
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
+void
+TimeInstantLayer::deleteSelection(Selection s)
+{
+    SparseOneDimensionalModel::EditCommand *command =
+	new SparseOneDimensionalModel::EditCommand(m_model,
+						   tr("Delete Selection"));
+
+    SparseOneDimensionalModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+	if (s.contains(i->frame)) command->deletePoint(*i);
+    }
+
+    command->finish();
+}
+  
+
 QString
 TimeInstantLayer::toXmlString(QString indent, QString extraAttributes) const
 {
--- a/layer/TimeInstantLayer.h	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/TimeInstantLayer.h	Wed Mar 01 18:13:01 2006 +0000
@@ -42,6 +42,10 @@
     virtual void editDrag(QMouseEvent *);
     virtual void editEnd(QMouseEvent *);
 
+    virtual void moveSelection(Selection s, size_t newStartFrame);
+    virtual void resizeSelection(Selection s, Selection newSize);
+    virtual void deleteSelection(Selection s);
+
     virtual const Model *getModel() const { return m_model; }
     void setModel(SparseOneDimensionalModel *model);
 
--- a/layer/TimeValueLayer.cpp	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/TimeValueLayer.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -695,6 +695,63 @@
     m_editing = false;
 }
 
+void
+TimeValueLayer::moveSelection(Selection s, size_t newStartFrame)
+{
+    SparseTimeValueModel::EditCommand *command =
+	new SparseTimeValueModel::EditCommand(m_model,
+					      tr("Drag Selection"));
+
+    SparseTimeValueModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    for (SparseTimeValueModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+	    SparseTimeValueModel::Point newPoint(*i);
+	    newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
+void
+TimeValueLayer::resizeSelection(Selection s, Selection newSize)
+{
+    SparseTimeValueModel::EditCommand *command =
+	new SparseTimeValueModel::EditCommand(m_model,
+					      tr("Resize Selection"));
+
+    SparseTimeValueModel::PointList points =
+	m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    double ratio =
+	double(newSize.getEndFrame() - newSize.getStartFrame()) /
+	double(s.getEndFrame() - s.getStartFrame());
+
+    for (SparseTimeValueModel::PointList::iterator i = points.begin();
+	 i != points.end(); ++i) {
+
+	if (s.contains(i->frame)) {
+
+	    double target = i->frame;
+	    target = newSize.getStartFrame() + 
+		double(target - s.getStartFrame()) * ratio;
+
+	    SparseTimeValueModel::Point newPoint(*i);
+	    newPoint.frame = lrint(target);
+	    command->deletePoint(*i);
+	    command->addPoint(newPoint);
+	}
+    }
+
+    command->finish();
+}
+
 QString
 TimeValueLayer::toXmlString(QString indent, QString extraAttributes) const
 {
--- a/layer/TimeValueLayer.h	Mon Feb 27 17:34:41 2006 +0000
+++ b/layer/TimeValueLayer.h	Wed Mar 01 18:13:01 2006 +0000
@@ -45,6 +45,9 @@
     virtual void editDrag(QMouseEvent *);
     virtual void editEnd(QMouseEvent *);
 
+    virtual void moveSelection(Selection s, size_t newStartFrame);
+    virtual void resizeSelection(Selection s, Selection newSize);
+
     virtual const Model *getModel() const { return m_model; }
     void setModel(SparseTimeValueModel *model);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/LayerTree.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -0,0 +1,207 @@
+
+/* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    A waveform viewer and audio annotation editor.
+    Chris Cannam, Queen Mary University of London, 2005-2006
+    
+    This is experimental software.  Not for distribution.
+*/
+
+#include "LayerTree.h"
+#include "PaneStack.h"
+
+#include "widgets/Pane.h"
+#include "base/Layer.h"
+
+#include <iostream>
+
+
+LayerTreeModel::LayerTreeModel(PaneStack *stack, QObject *parent) :
+    QAbstractItemModel(parent),
+    m_stack(stack)
+{
+}
+
+LayerTreeModel::~LayerTreeModel()
+{
+}
+
+QVariant
+LayerTreeModel::data(const QModelIndex &index, int role) const
+{
+    std::cerr << "LayerTreeModel::data(" << &index << ", role " << role << ")" << std::endl;
+
+    if (!index.isValid()) return QVariant();
+    if (role != Qt::DisplayRole) return QVariant();
+
+    QObject *obj = static_cast<QObject *>(index.internalPointer());
+    
+    PaneStack *paneStack = dynamic_cast<PaneStack *>(obj);
+    if (paneStack) {
+	std::cerr << "node is pane stack" << std::endl;
+	return QVariant("Pane stack");
+    }
+
+    Pane *pane = dynamic_cast<Pane *>(obj);
+    if (pane) {
+	// need index of pane in pane stack
+	for (int i = 0; i < m_stack->getPaneCount(); ++i) {
+	    if (pane == m_stack->getPane(i)) {
+		std::cerr << "node is pane " << i << std::endl;
+		return QVariant(QString("Pane %1").arg(i + 1));
+	    }
+	}
+	return QVariant();
+    }
+
+    Layer *layer = dynamic_cast<Layer *>(obj);
+    if (layer) {
+	std::cerr << "node is layer" << std::endl;
+	return QVariant(QString("%1").arg(layer->objectName()));
+    }
+
+    return QVariant();
+}
+
+/*
+Qt::ItemFlags
+LayerTreeModel::flags(const QModelIndex &index) const
+{
+}
+
+QVariant
+LayerTreeModel::headerData(const QModelIndex &index,
+			   Qt::Orientation orientation,
+			   int role) const
+{
+}
+*/
+
+QModelIndex
+LayerTreeModel::index(int row, int column, const QModelIndex &parent) const
+{
+    std::cerr << "LayerTreeModel::index(" << row << ", " << column << ", "
+	      << &parent << ")" << std::endl;
+
+    if (!parent.isValid()) {
+	// this is the pane stack
+	std::cerr << "parent invalid, returning pane stack as root" << std::endl;
+	return createIndex(row, column, m_stack);
+    }
+
+    QObject *obj = static_cast<QObject *>(parent.internalPointer());
+    
+    PaneStack *paneStack = dynamic_cast<PaneStack *>(obj);
+    if (paneStack) {
+	if (paneStack == m_stack && row < m_stack->getPaneCount()) {
+	    std::cerr << "parent is pane stack, returning a pane" << std::endl;
+	    return createIndex(row, column, m_stack->getPane(row));
+	}
+	std::cerr << "parent is wrong pane stack, returning nothing" << std::endl;
+	return QModelIndex();
+    }
+
+    Pane *pane = dynamic_cast<Pane *>(obj);
+    if (pane) {
+	if (row < pane->getLayerCount()) {
+	    std::cerr << "parent is pane, returning layer" << std::endl;
+	    return createIndex(row, column, pane->getLayer(row));
+	}
+    }
+
+    std::cerr << "unknown parent, returning nothing" << std::endl;
+    return QModelIndex();
+}
+
+QModelIndex
+LayerTreeModel::parent(const QModelIndex &index) const
+{
+    std::cerr << "LayerTreeModel::parent(" << &index << ")" << std::endl;
+
+    QObject *obj = static_cast<QObject *>(index.internalPointer());
+    
+    PaneStack *paneStack = dynamic_cast<PaneStack *>(obj);
+    if (paneStack) {
+	std::cerr << "node is pane stack, returning no parent" << std::endl;
+	return QModelIndex();
+    }
+
+    Pane *pane = dynamic_cast<Pane *>(obj);
+    if (pane) {
+	std::cerr << "node is pane, returning pane stack as parent" << std::endl;
+	return createIndex(0, 0, m_stack);
+    }
+
+    Layer *layer = dynamic_cast<Layer *>(obj);
+    if (layer) {
+	const View *view = layer->getView();
+	Pane *pane = const_cast<Pane *>(dynamic_cast<const Pane *>(view));
+	if (pane) {
+	    // need index of pane in pane stack
+	    for (int i = 0; i < m_stack->getPaneCount(); ++i) {
+		if (pane == m_stack->getPane(i)) {
+		    std::cerr << "node is layer, returning pane " << i << " as parent" << std::endl;
+		    return createIndex(i, 0, pane);
+		}
+	    }
+	}
+	std::cerr << "node is layer, but no parent found" << std::endl;
+	return QModelIndex();
+    }
+
+	
+
+    std::cerr << "unknown node" << std::endl;
+    return QModelIndex();
+}
+
+int
+LayerTreeModel::rowCount(const QModelIndex &parent) const
+{
+    std::cerr << "LayerTreeModel::rowCount(" << &parent << ")" << std::endl;
+
+    if (!parent.isValid()) {
+	std::cerr << "parent invalid, returning 1 for the pane stack" << std::endl;
+	return 1; // the pane stack
+    }
+
+    QObject *obj = static_cast<QObject *>(parent.internalPointer());
+    
+    PaneStack *paneStack = dynamic_cast<PaneStack *>(obj);
+    if (paneStack) {
+	if (paneStack == m_stack) {
+	    std::cerr << "parent is pane stack, returning "
+		      << m_stack->getPaneCount() << " panes" << std::endl;
+	    return m_stack->getPaneCount();
+	} else {
+	    return 0;
+	}
+    }
+ 
+    Pane *pane = dynamic_cast<Pane *>(obj);
+    if (pane) {
+	std::cerr << "parent is pane, returning "
+		  << pane->getLayerCount() << " layers" << std::endl;
+	return pane->getLayerCount();
+    }
+
+    std::cerr << "parent unknown, returning 0" << std::endl;
+    return 0;
+}
+
+int
+LayerTreeModel::columnCount(const QModelIndex &parent) const
+{
+    if (!parent.isValid()) return 1;
+
+    QObject *obj = static_cast<QObject *>(parent.internalPointer());
+    
+    Pane *pane = dynamic_cast<Pane *>(obj);
+    if (pane) {
+	return 1; // 2; // layer and model
+    }
+
+    return 1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/LayerTree.h	Wed Mar 01 18:13:01 2006 +0000
@@ -0,0 +1,45 @@
+
+/* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    A waveform viewer and audio annotation editor.
+    Chris Cannam, Queen Mary University of London, 2005-2006
+    
+    This is experimental software.  Not for distribution.
+*/
+
+#ifndef _LAYER_TREE_H_
+#define _LAYER_TREE_H_
+
+#include <QAbstractItemModel>
+
+class PaneStack;
+
+class LayerTreeModel : public QAbstractItemModel
+{
+    Q_OBJECT
+
+public:
+    LayerTreeModel(PaneStack *stack, QObject *parent = 0);
+    virtual ~LayerTreeModel();
+
+    QVariant data(const QModelIndex &index, int role) const;
+
+//    Qt::ItemFlags flags(const QModelIndex &index) const;
+
+//    QVariant headerData(int section, Qt::Orientation orientation,
+//                        int role = Qt::DisplayRole) const;
+
+    QModelIndex index(int row, int column,
+                      const QModelIndex &parent = QModelIndex()) const;
+
+    QModelIndex parent(const QModelIndex &index) const;
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+protected:
+    PaneStack *m_stack;
+};
+
+#endif
--- a/widgets/Pane.cpp	Mon Feb 27 17:34:41 2006 +0000
+++ b/widgets/Pane.cpp	Wed Mar 01 18:13:01 2006 +0000
@@ -817,6 +817,12 @@
 bool
 Pane::editSelectionStart(QMouseEvent *e)
 {
+    if (!m_identifyFeatures ||
+	!m_manager ||
+	m_manager->getToolMode() != ViewManager::EditMode) {
+	return false;
+    }
+
     bool closeToLeft, closeToRight;
     Selection s(getSelectionAt(e->x(), closeToLeft, closeToRight));
     if (s.isEmpty()) return false;
@@ -839,6 +845,42 @@
 Pane::editSelectionEnd(QMouseEvent *e)
 {
     if (m_editingSelection.isEmpty()) return false;
+
+    int offset = m_mousePos.x() - m_clickPos.x();
+    Layer *layer = getSelectedLayer();
+
+    if (offset == 0 || !layer) {
+	m_editingSelection = Selection();
+	return true;
+    }
+
+    int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset;
+    int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset;
+
+    long f0 = getFrameForX(p0);
+    long f1 = getFrameForX(p1);
+
+    Selection newSelection(f0, f1);
+    
+    if (m_editingSelectionEdge == 0) {
+	
+	layer->moveSelection(m_editingSelection, f0);
+	
+    } else {
+	
+	if (m_editingSelectionEdge < 0) {
+	    f1 = m_editingSelection.getEndFrame();
+	} else {
+	    f0 = m_editingSelection.getStartFrame();
+	}
+
+	newSelection = Selection(f0, f1);
+	layer->resizeSelection(m_editingSelection, newSelection);
+    }
+    
+    m_manager->removeSelection(m_editingSelection);
+    m_manager->addSelection(newSelection);
+
     m_editingSelection = Selection();
     return true;
 }
--- a/widgets/PaneStack.h	Mon Feb 27 17:34:41 2006 +0000
+++ b/widgets/PaneStack.h	Wed Mar 01 18:13:01 2006 +0000
@@ -30,9 +30,12 @@
 
     Pane *addPane(bool suppressPropertyBox = false); // I own the returned value
     Pane *getPane(int n); // I own the returned value
-    void deletePane(Pane *pane); // Deletes the pane and all its views
+    void deletePane(Pane *pane); // Deletes the pane and all its layers
     int getPaneCount() const;
 
+//!!!    void hidePane(Pane *pane);
+//    void showPane(Pane *pane);
+
     void setCurrentPane(Pane *pane);
     void setCurrentLayer(Pane *pane, Layer *layer);
     Pane *getCurrentPane();