mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-19 01:04:20 +00:00
Refactored some TreeView key handling. Introjucer: now restores the last set of open documents for a project.
This commit is contained in:
parent
3d72789127
commit
25e7361f2c
13 changed files with 309 additions and 123 deletions
|
|
@ -94,6 +94,7 @@ void MainWindow::createProjectContentCompIfNeeded()
|
|||
{
|
||||
clearContentComponent();
|
||||
setContentOwned (JucerApplication::getApp()->createProjectContentComponent(), false);
|
||||
jassert (getProjectContentComponent() != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,13 +127,17 @@ bool MainWindow::closeProject (Project* project)
|
|||
|
||||
getAppProperties().setValue (getProjectWindowPosName(), getWindowStateAsString());
|
||||
|
||||
if (! JucerApplication::getApp()->openDocumentManager.closeAllDocumentsUsingProject (*project, true))
|
||||
return false;
|
||||
|
||||
ProjectContentComponent* const pcc = getProjectContentComponent();
|
||||
|
||||
if (pcc != nullptr)
|
||||
{
|
||||
pcc->saveTreeViewState();
|
||||
pcc->saveOpenDocumentList();
|
||||
pcc->hideEditor();
|
||||
}
|
||||
|
||||
if (! JucerApplication::getApp()->openDocumentManager.closeAllDocumentsUsingProject (*project, true))
|
||||
return false;
|
||||
|
||||
FileBasedDocument::SaveResult r = project->saveIfNeededAndUserAgrees();
|
||||
|
||||
|
|
@ -373,6 +378,10 @@ bool MainWindowList::openFile (const File& file)
|
|||
w->setProject (newDoc.release());
|
||||
w->makeVisible();
|
||||
avoidSuperimposedWindows (w);
|
||||
|
||||
jassert (w->getProjectContentComponent() != nullptr);
|
||||
w->getProjectContentComponent()->reloadLastOpenDocuments();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ public:
|
|||
Component* createEditor() { return new ItemPreviewComponent (file); }
|
||||
Component* createViewer() { return createEditor(); }
|
||||
void fileHasBeenRenamed (const File& newFile) { file = newFile; }
|
||||
String getState() const { return String::empty; }
|
||||
void restoreState (const String& state) {}
|
||||
|
||||
String getType() const
|
||||
{
|
||||
|
|
@ -318,7 +320,7 @@ void RecentDocumentList::clear()
|
|||
|
||||
void RecentDocumentList::newDocumentOpened (OpenDocumentManager::Document* document)
|
||||
{
|
||||
if (document != getCurrentDocument())
|
||||
if (document != nullptr && document != getCurrentDocument())
|
||||
{
|
||||
nextDocs.clear();
|
||||
previousDocs.add (document);
|
||||
|
|
@ -371,3 +373,62 @@ void RecentDocumentList::documentAboutToClose (OpenDocumentManager::Document* do
|
|||
jassert (! previousDocs.contains (document));
|
||||
jassert (! nextDocs.contains (document));
|
||||
}
|
||||
|
||||
static void restoreDocList (Project& project, Array <OpenDocumentManager::Document*>& list, const XmlElement* xml)
|
||||
{
|
||||
if (xml != nullptr)
|
||||
{
|
||||
OpenDocumentManager& odm = JucerApplication::getApp()->openDocumentManager;
|
||||
|
||||
forEachXmlChildElementWithTagName (*xml, e, "DOC")
|
||||
{
|
||||
const File file (e->getStringAttribute ("file"));
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
OpenDocumentManager::Document* doc = odm.openFile (&project, file);
|
||||
|
||||
if (doc != nullptr)
|
||||
{
|
||||
doc->restoreState (e->getStringAttribute ("state"));
|
||||
|
||||
list.add (doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecentDocumentList::restoreFromXML (Project& project, const XmlElement& xml)
|
||||
{
|
||||
clear();
|
||||
|
||||
if (xml.hasTagName ("RECENT_DOCUMENTS"))
|
||||
{
|
||||
restoreDocList (project, previousDocs, xml.getChildByName ("PREVIOUS"));
|
||||
restoreDocList (project, nextDocs, xml.getChildByName ("NEXT"));
|
||||
}
|
||||
}
|
||||
|
||||
static void saveDocList (const Array <OpenDocumentManager::Document*>& list, XmlElement& xml)
|
||||
{
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
const OpenDocumentManager::Document& doc = *list.getUnchecked(i);
|
||||
|
||||
XmlElement* e = xml.createNewChildElement ("DOC");
|
||||
|
||||
e->setAttribute ("file", doc.getFile().getFullPathName());
|
||||
e->setAttribute ("state", doc.getState());
|
||||
}
|
||||
}
|
||||
|
||||
XmlElement* RecentDocumentList::createXML() const
|
||||
{
|
||||
XmlElement* xml = new XmlElement ("RECENT_DOCUMENTS");
|
||||
|
||||
saveDocList (previousDocs, *xml->createNewChildElement ("PREVIOUS"));
|
||||
saveDocList (nextDocs, *xml->createNewChildElement ("NEXT"));
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ public:
|
|||
virtual Component* createEditor() = 0;
|
||||
virtual Component* createViewer() = 0;
|
||||
virtual void fileHasBeenRenamed (const File& newFile) = 0;
|
||||
virtual String getState() const = 0;
|
||||
virtual void restoreState (const String& state) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -122,6 +124,8 @@ public:
|
|||
RecentDocumentList();
|
||||
~RecentDocumentList();
|
||||
|
||||
void clear();
|
||||
|
||||
void newDocumentOpened (OpenDocumentManager::Document* document);
|
||||
|
||||
OpenDocumentManager::Document* getCurrentDocument() const { return previousDocs.getLast(); }
|
||||
|
|
@ -134,7 +138,8 @@ public:
|
|||
|
||||
OpenDocumentManager::Document* getClosestPreviousDocOtherThan (OpenDocumentManager::Document* oneToAvoid) const;
|
||||
|
||||
void clear();
|
||||
void restoreFromXML (Project& project, const XmlElement& xml);
|
||||
XmlElement* createXML() const;
|
||||
|
||||
private:
|
||||
void documentAboutToClose (OpenDocumentManager::Document*);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ SourceCodeEditor::~SourceCodeEditor()
|
|||
SourceCodeDocument* doc = dynamic_cast <SourceCodeDocument*> (getDocument());
|
||||
|
||||
if (doc != nullptr)
|
||||
doc->updateLastPosition (*editor);
|
||||
doc->updateLastState (*editor);
|
||||
}
|
||||
|
||||
void SourceCodeEditor::createEditor (CodeDocument& codeDocument)
|
||||
|
|
@ -97,22 +97,45 @@ void SourceCodeEditor::valueTreeParentChanged (ValueTree&)
|
|||
void SourceCodeEditor::valueTreeRedirected (ValueTree&) { updateColourScheme(); }
|
||||
|
||||
//==============================================================================
|
||||
SourceCodeDocument::SourceCodeDocument (Project* project_, const File& file_)
|
||||
: modDetector (file_), project (project_)
|
||||
{
|
||||
}
|
||||
|
||||
CodeDocument& SourceCodeDocument::getCodeDocument()
|
||||
{
|
||||
if (codeDoc == nullptr)
|
||||
{
|
||||
codeDoc = new CodeDocument();
|
||||
reloadInternal();
|
||||
}
|
||||
|
||||
return *codeDoc;
|
||||
}
|
||||
|
||||
Component* SourceCodeDocument::createEditor()
|
||||
{
|
||||
SourceCodeEditor* e = new SourceCodeEditor (this);
|
||||
e->createEditor (codeDoc);
|
||||
applyLastPosition (*(e->editor));
|
||||
e->createEditor (getCodeDocument());
|
||||
applyLastState (*(e->editor));
|
||||
return e;
|
||||
}
|
||||
|
||||
void SourceCodeDocument::reloadFromFile()
|
||||
{
|
||||
getCodeDocument();
|
||||
reloadInternal();
|
||||
}
|
||||
|
||||
void SourceCodeDocument::reloadInternal()
|
||||
{
|
||||
jassert (codeDoc != nullptr);
|
||||
modDetector.updateHash();
|
||||
|
||||
ScopedPointer <InputStream> in (modDetector.getFile().createInputStream());
|
||||
|
||||
if (in != nullptr)
|
||||
codeDoc.loadFromStream (*in);
|
||||
codeDoc->loadFromStream (*in);
|
||||
}
|
||||
|
||||
bool SourceCodeDocument::save()
|
||||
|
|
@ -122,24 +145,24 @@ bool SourceCodeDocument::save()
|
|||
{
|
||||
FileOutputStream fo (temp.getFile());
|
||||
|
||||
if (! (fo.openedOk() && codeDoc.writeToStream (fo)))
|
||||
if (! (fo.openedOk() && getCodeDocument().writeToStream (fo)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! temp.overwriteTargetFileWithTemporary())
|
||||
return false;
|
||||
|
||||
codeDoc.setSavePoint();
|
||||
getCodeDocument().setSavePoint();
|
||||
modDetector.updateHash();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SourceCodeDocument::updateLastPosition (CodeEditorComponent& editor)
|
||||
void SourceCodeDocument::updateLastState (CodeEditorComponent& editor)
|
||||
{
|
||||
lastState = new CodeEditorComponent::State (editor);
|
||||
}
|
||||
|
||||
void SourceCodeDocument::applyLastPosition (CodeEditorComponent& editor) const
|
||||
void SourceCodeDocument::applyLastState (CodeEditorComponent& editor) const
|
||||
{
|
||||
if (lastState != nullptr)
|
||||
lastState->restoreState (editor);
|
||||
|
|
|
|||
|
|
@ -35,11 +35,32 @@ class SourceCodeDocument : public OpenDocumentManager::Document
|
|||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
SourceCodeDocument (Project* project_, const File& file_)
|
||||
: modDetector (file_), project (project_)
|
||||
{
|
||||
reloadFromFile();
|
||||
}
|
||||
SourceCodeDocument (Project*, const File&);
|
||||
|
||||
bool loadedOk() const { return true; }
|
||||
bool isForFile (const File& file) const { return getFile() == file; }
|
||||
bool isForNode (const ValueTree& node) const { return false; }
|
||||
bool refersToProject (Project& p) const { return project == &p; }
|
||||
Project* getProject() const { return project; }
|
||||
String getName() const { return getFile().getFileName(); }
|
||||
String getType() const { return getFile().getFileExtension() + " file"; }
|
||||
File getFile() const { return modDetector.getFile(); }
|
||||
bool needsSaving() const { return codeDoc != nullptr && codeDoc->hasChangedSinceSavePoint(); }
|
||||
bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); }
|
||||
void fileHasBeenRenamed (const File& newFile) { modDetector.fileHasBeenRenamed (newFile); }
|
||||
String getState() const { return lastState != nullptr ? lastState->toString() : String::empty; }
|
||||
void restoreState (const String& state) { lastState = new CodeEditorComponent::State (state); }
|
||||
|
||||
void reloadFromFile();
|
||||
bool save();
|
||||
|
||||
Component* createEditor();
|
||||
Component* createViewer() { return createEditor(); }
|
||||
|
||||
void updateLastState (CodeEditorComponent& editor);
|
||||
void applyLastState (CodeEditorComponent& editor) const;
|
||||
|
||||
CodeDocument& getCodeDocument();
|
||||
|
||||
//==============================================================================
|
||||
struct Type : public OpenDocumentManager::DocumentType
|
||||
|
|
@ -48,34 +69,14 @@ public:
|
|||
Document* openFile (Project* project, const File& file) { return new SourceCodeDocument (project, file); }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
bool loadedOk() const { return true; }
|
||||
bool isForFile (const File& file) const { return getFile() == file; }
|
||||
bool isForNode (const ValueTree& node) const { return false; }
|
||||
bool refersToProject (Project& p) const { return project == &p; }
|
||||
Project* getProject() const { return project; }
|
||||
String getName() const { return getFile().getFileName(); }
|
||||
String getType() const { return getFile().getFileExtension() + " file"; }
|
||||
File getFile() const { return modDetector.getFile(); }
|
||||
bool needsSaving() const { return codeDoc.hasChangedSinceSavePoint(); }
|
||||
bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); }
|
||||
void fileHasBeenRenamed (const File& newFile) { modDetector.fileHasBeenRenamed (newFile); }
|
||||
|
||||
void reloadFromFile();
|
||||
bool save();
|
||||
|
||||
Component* createEditor();
|
||||
Component* createViewer() { return createEditor(); }
|
||||
|
||||
void updateLastPosition (CodeEditorComponent& editor);
|
||||
void applyLastPosition (CodeEditorComponent& editor) const;
|
||||
|
||||
protected:
|
||||
FileModificationDetector modDetector;
|
||||
CodeDocument codeDoc;
|
||||
ScopedPointer<CodeDocument> codeDoc;
|
||||
Project* project;
|
||||
|
||||
ScopedPointer<CodeEditorComponent::State> lastState;
|
||||
|
||||
void reloadInternal();
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -218,6 +218,31 @@ void ProjectContentComponent::saveTreeViewState()
|
|||
}
|
||||
}
|
||||
|
||||
void ProjectContentComponent::saveOpenDocumentList()
|
||||
{
|
||||
if (project != nullptr)
|
||||
{
|
||||
ScopedPointer<XmlElement> xml (recentDocumentList.createXML());
|
||||
|
||||
if (xml != nullptr)
|
||||
getAppProperties().setValue ("lastDocs_" + project->getProjectUID(), xml);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectContentComponent::reloadLastOpenDocuments()
|
||||
{
|
||||
if (project != nullptr)
|
||||
{
|
||||
ScopedPointer<XmlElement> xml (getAppProperties().getXmlValue ("lastDocs_" + project->getProjectUID()));
|
||||
|
||||
if (xml != nullptr)
|
||||
{
|
||||
recentDocumentList.restoreFromXML (*project, *xml);
|
||||
showDocument (recentDocumentList.getCurrentDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster*)
|
||||
{
|
||||
updateMissingFileStatuses();
|
||||
|
|
@ -251,8 +276,11 @@ bool ProjectContentComponent::showDocument (OpenDocumentManager::Document* doc)
|
|||
if (doc->hasFileBeenModifiedExternally())
|
||||
doc->reloadFromFile();
|
||||
|
||||
if (doc == getCurrentDocument())
|
||||
if (doc == getCurrentDocument() && contentView != nullptr)
|
||||
{
|
||||
contentView->grabKeyboardFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
recentDocumentList.newDocumentOpened (doc);
|
||||
|
||||
|
|
@ -265,7 +293,6 @@ void ProjectContentComponent::hideEditor()
|
|||
contentView = nullptr;
|
||||
updateMainWindowTitle();
|
||||
commandManager->commandStatusChanged();
|
||||
recentDocumentList.clear();
|
||||
}
|
||||
|
||||
void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc)
|
||||
|
|
@ -303,7 +330,12 @@ bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumen
|
|||
|
||||
bool ProjectContentComponent::goToPreviousFile()
|
||||
{
|
||||
return showDocument (recentDocumentList.getPrevious());
|
||||
OpenDocumentManager::Document* currentSourceDoc = recentDocumentList.getCurrentDocument();
|
||||
|
||||
if (currentSourceDoc != nullptr && currentSourceDoc != getCurrentDocument())
|
||||
return showDocument (currentSourceDoc);
|
||||
else
|
||||
return showDocument (recentDocumentList.getPrevious());
|
||||
}
|
||||
|
||||
bool ProjectContentComponent::goToNextFile()
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ public:
|
|||
|
||||
Project* getProject() const noexcept { return project; }
|
||||
virtual void setProject (Project* project);
|
||||
|
||||
void saveTreeViewState();
|
||||
void saveOpenDocumentList();
|
||||
void reloadLastOpenDocuments();
|
||||
|
||||
bool showEditorForFile (const File& f);
|
||||
File getCurrentFile() const;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ public:
|
|||
void itemSelectionChanged (bool isNowSelected);
|
||||
void itemDoubleClicked (const MouseEvent&);
|
||||
|
||||
void cancelDelayedSelectionTimer();
|
||||
|
||||
//==============================================================================
|
||||
virtual Font getFont() const;
|
||||
virtual String getRenamingName() const = 0;
|
||||
|
|
@ -89,7 +91,6 @@ public:
|
|||
|
||||
protected:
|
||||
ProjectContentComponent* getProjectContentComponent() const;
|
||||
void cancelDelayedSelectionTimer();
|
||||
virtual void addSubItems() {}
|
||||
|
||||
private:
|
||||
|
|
@ -128,7 +129,17 @@ public:
|
|||
|
||||
const ScopedPointer<XmlElement> treeOpenness (getAppProperties().getXmlValue (opennessStateKey));
|
||||
if (treeOpenness != nullptr)
|
||||
{
|
||||
tree.restoreOpennessState (*treeOpenness, true);
|
||||
|
||||
for (int i = tree.getNumSelectedItems(); --i >= 0;)
|
||||
{
|
||||
JucerTreeViewBase* item = dynamic_cast<JucerTreeViewBase*> (tree.getSelectedItem (i));
|
||||
|
||||
if (item != nullptr)
|
||||
item->cancelDelayedSelectionTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void saveOpenness()
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ public:
|
|||
|
||||
/** Represents a combination of all the mouse buttons at once. */
|
||||
allMouseButtonModifiers = leftButtonModifier | rightButtonModifier | middleButtonModifier,
|
||||
|
||||
/** Represents a combination of all the alt, ctrl and command key modifiers. */
|
||||
ctrlAltCommandModifiers = ctrlModifier | altModifier | commandModifier
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -171,11 +174,11 @@ public:
|
|||
/** Returns the raw flags for direct testing. */
|
||||
inline int getRawFlags() const noexcept { return flags; }
|
||||
|
||||
inline const ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept { return ModifierKeys (flags & ~rawFlagsToClear); }
|
||||
inline const ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); }
|
||||
ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept { return ModifierKeys (flags & ~rawFlagsToClear); }
|
||||
ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); }
|
||||
|
||||
/** Tests a combination of flags and returns true if any of them are set. */
|
||||
inline bool testFlags (const int flagsToTest) const noexcept { return (flags & flagsToTest) != 0; }
|
||||
bool testFlags (const int flagsToTest) const noexcept { return (flags & flagsToTest) != 0; }
|
||||
|
||||
/** Returns the total number of mouse buttons that are down. */
|
||||
int getNumMouseButtonsDown() const noexcept;
|
||||
|
|
|
|||
|
|
@ -761,86 +761,100 @@ void TreeView::scrollToKeepItemVisible (TreeViewItem* item)
|
|||
}
|
||||
}
|
||||
|
||||
void TreeView::toggleOpenSelectedItem()
|
||||
{
|
||||
TreeViewItem* const firstSelected = getSelectedItem (0);
|
||||
if (firstSelected != nullptr)
|
||||
firstSelected->setOpen (! firstSelected->isOpen());
|
||||
}
|
||||
|
||||
void TreeView::moveOutOfSelectedItem()
|
||||
{
|
||||
TreeViewItem* const firstSelected = getSelectedItem (0);
|
||||
|
||||
if (firstSelected != nullptr)
|
||||
{
|
||||
if (firstSelected->isOpen())
|
||||
{
|
||||
firstSelected->setOpen (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeViewItem* parent = firstSelected->parentItem;
|
||||
|
||||
if ((! rootItemVisible) && parent == rootItem)
|
||||
parent = nullptr;
|
||||
|
||||
if (parent != nullptr)
|
||||
{
|
||||
parent->setSelected (true, true);
|
||||
scrollToKeepItemVisible (parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::moveIntoSelectedItem()
|
||||
{
|
||||
TreeViewItem* const firstSelected = getSelectedItem (0);
|
||||
|
||||
if (firstSelected != nullptr)
|
||||
{
|
||||
if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems())
|
||||
moveSelectedRow (1);
|
||||
else
|
||||
firstSelected->setOpen (true);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::moveByPages (int numPages)
|
||||
{
|
||||
TreeViewItem* currentItem = getSelectedItem (0);
|
||||
|
||||
if (currentItem != nullptr)
|
||||
{
|
||||
const Rectangle<int> pos (currentItem->getItemPosition (false));
|
||||
const int targetY = pos.getY() + numPages * (getHeight() - pos.getHeight());
|
||||
int currentRow = currentItem->getRowNumberInTree();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
moveSelectedRow (numPages);
|
||||
currentItem = getSelectedItem (0);
|
||||
|
||||
if (currentItem == nullptr)
|
||||
break;
|
||||
|
||||
const int y = currentItem->getItemPosition (false).getY();
|
||||
if ((numPages < 0 && y <= targetY) || (numPages > 0 && y >= targetY))
|
||||
break;
|
||||
|
||||
const int newRow = currentItem->getRowNumberInTree();
|
||||
if (newRow == currentRow)
|
||||
break;
|
||||
|
||||
currentRow = newRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TreeView::keyPressed (const KeyPress& key)
|
||||
{
|
||||
if (key.isKeyCode (KeyPress::upKey))
|
||||
if (rootItem != nullptr
|
||||
&& ! key.getModifiers().testFlags (ModifierKeys::ctrlAltCommandModifiers))
|
||||
{
|
||||
moveSelectedRow (-1);
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::downKey))
|
||||
{
|
||||
moveSelectedRow (1);
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::pageDownKey) || key.isKeyCode (KeyPress::pageUpKey))
|
||||
{
|
||||
if (rootItem != nullptr)
|
||||
{
|
||||
int rowsOnScreen = getHeight() / jmax (1, rootItem->itemHeight);
|
||||
|
||||
if (key.isKeyCode (KeyPress::pageUpKey))
|
||||
rowsOnScreen = -rowsOnScreen;
|
||||
|
||||
if (rowsOnScreen != 0)
|
||||
moveSelectedRow (rowsOnScreen);
|
||||
}
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::homeKey))
|
||||
{
|
||||
moveSelectedRow (-0x3fffffff);
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::endKey))
|
||||
{
|
||||
moveSelectedRow (0x3fffffff);
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::returnKey))
|
||||
{
|
||||
TreeViewItem* const firstSelected = getSelectedItem (0);
|
||||
if (firstSelected != nullptr)
|
||||
firstSelected->setOpen (! firstSelected->isOpen());
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::leftKey))
|
||||
{
|
||||
TreeViewItem* const firstSelected = getSelectedItem (0);
|
||||
|
||||
if (firstSelected != nullptr)
|
||||
{
|
||||
if (firstSelected->isOpen())
|
||||
{
|
||||
firstSelected->setOpen (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeViewItem* parent = firstSelected->parentItem;
|
||||
|
||||
if ((! rootItemVisible) && parent == rootItem)
|
||||
parent = nullptr;
|
||||
|
||||
if (parent != nullptr)
|
||||
{
|
||||
parent->setSelected (true, true);
|
||||
scrollToKeepItemVisible (parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (key.isKeyCode (KeyPress::rightKey))
|
||||
{
|
||||
TreeViewItem* const firstSelected = getSelectedItem (0);
|
||||
|
||||
if (firstSelected != nullptr)
|
||||
{
|
||||
if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems())
|
||||
moveSelectedRow (1);
|
||||
else
|
||||
firstSelected->setOpen (true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
if (key.getKeyCode() == KeyPress::upKey) { moveSelectedRow (-1); return true; }
|
||||
if (key.getKeyCode() == KeyPress::downKey) { moveSelectedRow (1); return true; }
|
||||
if (key.getKeyCode() == KeyPress::homeKey) { moveSelectedRow (-0x3fffffff); return true; }
|
||||
if (key.getKeyCode() == KeyPress::endKey) { moveSelectedRow (0x3fffffff); return true; }
|
||||
if (key.getKeyCode() == KeyPress::pageUpKey) { moveByPages (-1); return true; }
|
||||
if (key.getKeyCode() == KeyPress::pageDownKey) { moveByPages (1); return true; }
|
||||
if (key.getKeyCode() == KeyPress::returnKey) { toggleOpenSelectedItem(); return true; }
|
||||
if (key.getKeyCode() == KeyPress::leftKey) { moveOutOfSelectedItem(); return true; }
|
||||
if (key.getKeyCode() == KeyPress::rightKey) { moveIntoSelectedItem(); return true; }
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void TreeView::itemsChanged() noexcept
|
||||
|
|
|
|||
|
|
@ -820,6 +820,10 @@ private:
|
|||
void hideDragHighlight() noexcept;
|
||||
void handleDrag (const StringArray& files, const SourceDetails&);
|
||||
void handleDrop (const StringArray& files, const SourceDetails&);
|
||||
void toggleOpenSelectedItem();
|
||||
void moveOutOfSelectedItem();
|
||||
void moveIntoSelectedItem();
|
||||
void moveByPages (int numPages);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeView);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1425,3 +1425,18 @@ void CodeEditorComponent::State::restoreState (CodeEditorComponent& editor) cons
|
|||
if (lastTopLine > 0 && lastTopLine < editor.getDocument().getNumLines())
|
||||
editor.scrollToLine (lastTopLine);
|
||||
}
|
||||
|
||||
CodeEditorComponent::State::State (const String& s)
|
||||
{
|
||||
StringArray tokens;
|
||||
tokens.addTokens (s, ":", String::empty);
|
||||
|
||||
lastTopLine = tokens[0].getIntValue();
|
||||
lastCaretPos = tokens[1].getIntValue();
|
||||
lastSelectionEnd = tokens[2].getIntValue();
|
||||
}
|
||||
|
||||
String CodeEditorComponent::State::toString() const
|
||||
{
|
||||
return String (lastTopLine) + ":" + String (lastCaretPos) + ":" + String (lastSelectionEnd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,11 +163,16 @@ public:
|
|||
{
|
||||
/** Creates an object containing the state of the given editor. */
|
||||
State (const CodeEditorComponent& editor);
|
||||
/** Creates a state object from a string that was previously created with toString(). */
|
||||
State (const String& stringifiedVersion);
|
||||
State (const State& other) noexcept;
|
||||
|
||||
/** Updates the given editor with this saved state. */
|
||||
void restoreState (CodeEditorComponent& editor) const;
|
||||
|
||||
/** Returns a stringified version of this state that can be used to recreate it later. */
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
int lastTopLine, lastCaretPos, lastSelectionEnd;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue