Browse Source

Refactored some TreeView key handling. Introjucer: now restores the last set of open documents for a project.

tags/2021-05-28
jules 13 years ago
parent
commit
25e7361f2c
13 changed files with 294 additions and 108 deletions
  1. +12
    -3
      extras/Introjucer/Source/Application/jucer_MainWindow.cpp
  2. +62
    -1
      extras/Introjucer/Source/Application/jucer_OpenDocumentManager.cpp
  3. +6
    -1
      extras/Introjucer/Source/Application/jucer_OpenDocumentManager.h
  4. +31
    -8
      extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp
  5. +29
    -28
      extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h
  6. +35
    -3
      extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp
  7. +3
    -0
      extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h
  8. +12
    -1
      extras/Introjucer/Source/Utility/jucer_JucerTreeViewBase.h
  9. +6
    -3
      modules/juce_gui_basics/keyboard/juce_ModifierKeys.h
  10. +74
    -60
      modules/juce_gui_basics/widgets/juce_TreeView.cpp
  11. +4
    -0
      modules/juce_gui_basics/widgets/juce_TreeView.h
  12. +15
    -0
      modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp
  13. +5
    -0
      modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.h

+ 12
- 3
extras/Introjucer/Source/Application/jucer_MainWindow.cpp View File

@@ -94,6 +94,7 @@ void MainWindow::createProjectContentCompIfNeeded()
{ {
clearContentComponent(); clearContentComponent();
setContentOwned (JucerApplication::getApp()->createProjectContentComponent(), false); setContentOwned (JucerApplication::getApp()->createProjectContentComponent(), false);
jassert (getProjectContentComponent() != nullptr);
} }
} }
@@ -126,13 +127,17 @@ bool MainWindow::closeProject (Project* project)
getAppProperties().setValue (getProjectWindowPosName(), getWindowStateAsString()); getAppProperties().setValue (getProjectWindowPosName(), getWindowStateAsString());
if (! JucerApplication::getApp()->openDocumentManager.closeAllDocumentsUsingProject (*project, true))
return false;
ProjectContentComponent* const pcc = getProjectContentComponent(); ProjectContentComponent* const pcc = getProjectContentComponent();
if (pcc != nullptr) if (pcc != nullptr)
{
pcc->saveTreeViewState(); pcc->saveTreeViewState();
pcc->saveOpenDocumentList();
pcc->hideEditor();
}
if (! JucerApplication::getApp()->openDocumentManager.closeAllDocumentsUsingProject (*project, true))
return false;
FileBasedDocument::SaveResult r = project->saveIfNeededAndUserAgrees(); FileBasedDocument::SaveResult r = project->saveIfNeededAndUserAgrees();
@@ -373,6 +378,10 @@ bool MainWindowList::openFile (const File& file)
w->setProject (newDoc.release()); w->setProject (newDoc.release());
w->makeVisible(); w->makeVisible();
avoidSuperimposedWindows (w); avoidSuperimposedWindows (w);
jassert (w->getProjectContentComponent() != nullptr);
w->getProjectContentComponent()->reloadLastOpenDocuments();
return true; return true;
} }
} }


+ 62
- 1
extras/Introjucer/Source/Application/jucer_OpenDocumentManager.cpp View File

@@ -61,6 +61,8 @@ public:
Component* createEditor() { return new ItemPreviewComponent (file); } Component* createEditor() { return new ItemPreviewComponent (file); }
Component* createViewer() { return createEditor(); } Component* createViewer() { return createEditor(); }
void fileHasBeenRenamed (const File& newFile) { file = newFile; } void fileHasBeenRenamed (const File& newFile) { file = newFile; }
String getState() const { return String::empty; }
void restoreState (const String& state) {}
String getType() const String getType() const
{ {
@@ -318,7 +320,7 @@ void RecentDocumentList::clear()
void RecentDocumentList::newDocumentOpened (OpenDocumentManager::Document* document) void RecentDocumentList::newDocumentOpened (OpenDocumentManager::Document* document)
{ {
if (document != getCurrentDocument())
if (document != nullptr && document != getCurrentDocument())
{ {
nextDocs.clear(); nextDocs.clear();
previousDocs.add (document); previousDocs.add (document);
@@ -371,3 +373,62 @@ void RecentDocumentList::documentAboutToClose (OpenDocumentManager::Document* do
jassert (! previousDocs.contains (document)); jassert (! previousDocs.contains (document));
jassert (! nextDocs.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;
}

+ 6
- 1
extras/Introjucer/Source/Application/jucer_OpenDocumentManager.h View File

@@ -60,6 +60,8 @@ public:
virtual Component* createEditor() = 0; virtual Component* createEditor() = 0;
virtual Component* createViewer() = 0; virtual Component* createViewer() = 0;
virtual void fileHasBeenRenamed (const File& newFile) = 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();
~RecentDocumentList(); ~RecentDocumentList();
void clear();
void newDocumentOpened (OpenDocumentManager::Document* document); void newDocumentOpened (OpenDocumentManager::Document* document);
OpenDocumentManager::Document* getCurrentDocument() const { return previousDocs.getLast(); } OpenDocumentManager::Document* getCurrentDocument() const { return previousDocs.getLast(); }
@@ -134,7 +138,8 @@ public:
OpenDocumentManager::Document* getClosestPreviousDocOtherThan (OpenDocumentManager::Document* oneToAvoid) const; OpenDocumentManager::Document* getClosestPreviousDocOtherThan (OpenDocumentManager::Document* oneToAvoid) const;
void clear();
void restoreFromXML (Project& project, const XmlElement& xml);
XmlElement* createXML() const;
private: private:
void documentAboutToClose (OpenDocumentManager::Document*); void documentAboutToClose (OpenDocumentManager::Document*);


+ 31
- 8
extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp View File

@@ -40,7 +40,7 @@ SourceCodeEditor::~SourceCodeEditor()
SourceCodeDocument* doc = dynamic_cast <SourceCodeDocument*> (getDocument()); SourceCodeDocument* doc = dynamic_cast <SourceCodeDocument*> (getDocument());
if (doc != nullptr) if (doc != nullptr)
doc->updateLastPosition (*editor);
doc->updateLastState (*editor);
} }
void SourceCodeEditor::createEditor (CodeDocument& codeDocument) void SourceCodeEditor::createEditor (CodeDocument& codeDocument)
@@ -97,22 +97,45 @@ void SourceCodeEditor::valueTreeParentChanged (ValueTree&)
void SourceCodeEditor::valueTreeRedirected (ValueTree&) { updateColourScheme(); } 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() Component* SourceCodeDocument::createEditor()
{ {
SourceCodeEditor* e = new SourceCodeEditor (this); SourceCodeEditor* e = new SourceCodeEditor (this);
e->createEditor (codeDoc);
applyLastPosition (*(e->editor));
e->createEditor (getCodeDocument());
applyLastState (*(e->editor));
return e; return e;
} }
void SourceCodeDocument::reloadFromFile() void SourceCodeDocument::reloadFromFile()
{ {
getCodeDocument();
reloadInternal();
}
void SourceCodeDocument::reloadInternal()
{
jassert (codeDoc != nullptr);
modDetector.updateHash(); modDetector.updateHash();
ScopedPointer <InputStream> in (modDetector.getFile().createInputStream()); ScopedPointer <InputStream> in (modDetector.getFile().createInputStream());
if (in != nullptr) if (in != nullptr)
codeDoc.loadFromStream (*in);
codeDoc->loadFromStream (*in);
} }
bool SourceCodeDocument::save() bool SourceCodeDocument::save()
@@ -122,24 +145,24 @@ bool SourceCodeDocument::save()
{ {
FileOutputStream fo (temp.getFile()); FileOutputStream fo (temp.getFile());
if (! (fo.openedOk() && codeDoc.writeToStream (fo)))
if (! (fo.openedOk() && getCodeDocument().writeToStream (fo)))
return false; return false;
} }
if (! temp.overwriteTargetFileWithTemporary()) if (! temp.overwriteTargetFileWithTemporary())
return false; return false;
codeDoc.setSavePoint();
getCodeDocument().setSavePoint();
modDetector.updateHash(); modDetector.updateHash();
return true; return true;
} }
void SourceCodeDocument::updateLastPosition (CodeEditorComponent& editor)
void SourceCodeDocument::updateLastState (CodeEditorComponent& editor)
{ {
lastState = new CodeEditorComponent::State (editor); lastState = new CodeEditorComponent::State (editor);
} }
void SourceCodeDocument::applyLastPosition (CodeEditorComponent& editor) const
void SourceCodeDocument::applyLastState (CodeEditorComponent& editor) const
{ {
if (lastState != nullptr) if (lastState != nullptr)
lastState->restoreState (editor); lastState->restoreState (editor);


+ 29
- 28
extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h View File

@@ -35,31 +35,21 @@ class SourceCodeDocument : public OpenDocumentManager::Document
{ {
public: public:
//============================================================================== //==============================================================================
SourceCodeDocument (Project* project_, const File& file_)
: modDetector (file_), project (project_)
{
reloadFromFile();
}
//==============================================================================
struct Type : public OpenDocumentManager::DocumentType
{
bool canOpenFile (const File& file) { return file.hasFileExtension ("cpp;h;hpp;mm;m;c;cc;cxx;txt;inc;tcc;xml;plist;rtf;html;htm;php;py;rb;cs"); }
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); }
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(); void reloadFromFile();
bool save(); bool save();
@@ -67,15 +57,26 @@ public:
Component* createEditor(); Component* createEditor();
Component* createViewer() { return createEditor(); } Component* createViewer() { return createEditor(); }
void updateLastPosition (CodeEditorComponent& editor);
void applyLastPosition (CodeEditorComponent& editor) const;
void updateLastState (CodeEditorComponent& editor);
void applyLastState (CodeEditorComponent& editor) const;
CodeDocument& getCodeDocument();
//==============================================================================
struct Type : public OpenDocumentManager::DocumentType
{
bool canOpenFile (const File& file) { return file.hasFileExtension ("cpp;h;hpp;mm;m;c;cc;cxx;txt;inc;tcc;xml;plist;rtf;html;htm;php;py;rb;cs"); }
Document* openFile (Project* project, const File& file) { return new SourceCodeDocument (project, file); }
};
protected: protected:
FileModificationDetector modDetector; FileModificationDetector modDetector;
CodeDocument codeDoc;
ScopedPointer<CodeDocument> codeDoc;
Project* project; Project* project;
ScopedPointer<CodeEditorComponent::State> lastState; ScopedPointer<CodeEditorComponent::State> lastState;
void reloadInternal();
}; };
//============================================================================== //==============================================================================


+ 35
- 3
extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp View File

@@ -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*) void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster*)
{ {
updateMissingFileStatuses(); updateMissingFileStatuses();
@@ -251,8 +276,11 @@ bool ProjectContentComponent::showDocument (OpenDocumentManager::Document* doc)
if (doc->hasFileBeenModifiedExternally()) if (doc->hasFileBeenModifiedExternally())
doc->reloadFromFile(); doc->reloadFromFile();
if (doc == getCurrentDocument())
if (doc == getCurrentDocument() && contentView != nullptr)
{
contentView->grabKeyboardFocus();
return true; return true;
}
recentDocumentList.newDocumentOpened (doc); recentDocumentList.newDocumentOpened (doc);
@@ -265,7 +293,6 @@ void ProjectContentComponent::hideEditor()
contentView = nullptr; contentView = nullptr;
updateMainWindowTitle(); updateMainWindowTitle();
commandManager->commandStatusChanged(); commandManager->commandStatusChanged();
recentDocumentList.clear();
} }
void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc) void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc)
@@ -303,7 +330,12 @@ bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumen
bool ProjectContentComponent::goToPreviousFile() 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() bool ProjectContentComponent::goToNextFile()


+ 3
- 0
extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h View File

@@ -44,7 +44,10 @@ public:
Project* getProject() const noexcept { return project; } Project* getProject() const noexcept { return project; }
virtual void setProject (Project* project); virtual void setProject (Project* project);
void saveTreeViewState(); void saveTreeViewState();
void saveOpenDocumentList();
void reloadLastOpenDocuments();
bool showEditorForFile (const File& f); bool showEditorForFile (const File& f);
File getCurrentFile() const; File getCurrentFile() const;


+ 12
- 1
extras/Introjucer/Source/Utility/jucer_JucerTreeViewBase.h View File

@@ -46,6 +46,8 @@ public:
void itemSelectionChanged (bool isNowSelected); void itemSelectionChanged (bool isNowSelected);
void itemDoubleClicked (const MouseEvent&); void itemDoubleClicked (const MouseEvent&);
void cancelDelayedSelectionTimer();
//============================================================================== //==============================================================================
virtual Font getFont() const; virtual Font getFont() const;
virtual String getRenamingName() const = 0; virtual String getRenamingName() const = 0;
@@ -89,7 +91,6 @@ public:
protected: protected:
ProjectContentComponent* getProjectContentComponent() const; ProjectContentComponent* getProjectContentComponent() const;
void cancelDelayedSelectionTimer();
virtual void addSubItems() {} virtual void addSubItems() {}
private: private:
@@ -128,7 +129,17 @@ public:
const ScopedPointer<XmlElement> treeOpenness (getAppProperties().getXmlValue (opennessStateKey)); const ScopedPointer<XmlElement> treeOpenness (getAppProperties().getXmlValue (opennessStateKey));
if (treeOpenness != nullptr) if (treeOpenness != nullptr)
{
tree.restoreOpennessState (*treeOpenness, true); 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() void saveOpenness()


+ 6
- 3
modules/juce_gui_basics/keyboard/juce_ModifierKeys.h View File

@@ -155,6 +155,9 @@ public:
/** Represents a combination of all the mouse buttons at once. */ /** Represents a combination of all the mouse buttons at once. */
allMouseButtonModifiers = leftButtonModifier | rightButtonModifier | middleButtonModifier, 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. */ /** Returns the raw flags for direct testing. */
inline int getRawFlags() const noexcept { return flags; } 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. */ /** 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. */ /** Returns the total number of mouse buttons that are down. */
int getNumMouseButtonsDown() const noexcept; int getNumMouseButtonsDown() const noexcept;


+ 74
- 60
modules/juce_gui_basics/widgets/juce_TreeView.cpp View File

@@ -761,86 +761,100 @@ void TreeView::scrollToKeepItemVisible (TreeViewItem* item)
} }
} }
bool TreeView::keyPressed (const KeyPress& key)
void TreeView::toggleOpenSelectedItem()
{ {
if (key.isKeyCode (KeyPress::upKey))
{
moveSelectedRow (-1);
}
else if (key.isKeyCode (KeyPress::downKey))
{
moveSelectedRow (1);
}
else if (key.isKeyCode (KeyPress::pageDownKey) || key.isKeyCode (KeyPress::pageUpKey))
TreeViewItem* const firstSelected = getSelectedItem (0);
if (firstSelected != nullptr)
firstSelected->setOpen (! firstSelected->isOpen());
}
void TreeView::moveOutOfSelectedItem()
{
TreeViewItem* const firstSelected = getSelectedItem (0);
if (firstSelected != nullptr)
{ {
if (rootItem != nullptr)
if (firstSelected->isOpen())
{ {
int rowsOnScreen = getHeight() / jmax (1, rootItem->itemHeight);
firstSelected->setOpen (false);
}
else
{
TreeViewItem* parent = firstSelected->parentItem;
if (key.isKeyCode (KeyPress::pageUpKey))
rowsOnScreen = -rowsOnScreen;
if ((! rootItemVisible) && parent == rootItem)
parent = nullptr;
if (rowsOnScreen != 0)
moveSelectedRow (rowsOnScreen);
if (parent != nullptr)
{
parent->setSelected (true, true);
scrollToKeepItemVisible (parent);
}
} }
} }
else if (key.isKeyCode (KeyPress::homeKey))
{
moveSelectedRow (-0x3fffffff);
}
else if (key.isKeyCode (KeyPress::endKey))
{
moveSelectedRow (0x3fffffff);
}
else if (key.isKeyCode (KeyPress::returnKey))
}
void TreeView::moveIntoSelectedItem()
{
TreeViewItem* const firstSelected = getSelectedItem (0);
if (firstSelected != nullptr)
{ {
TreeViewItem* const firstSelected = getSelectedItem (0);
if (firstSelected != nullptr)
firstSelected->setOpen (! firstSelected->isOpen());
if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems())
moveSelectedRow (1);
else
firstSelected->setOpen (true);
} }
else if (key.isKeyCode (KeyPress::leftKey))
}
void TreeView::moveByPages (int numPages)
{
TreeViewItem* currentItem = getSelectedItem (0);
if (currentItem != nullptr)
{ {
TreeViewItem* const firstSelected = getSelectedItem (0);
const Rectangle<int> pos (currentItem->getItemPosition (false));
const int targetY = pos.getY() + numPages * (getHeight() - pos.getHeight());
int currentRow = currentItem->getRowNumberInTree();
if (firstSelected != nullptr)
for (;;)
{ {
if (firstSelected->isOpen())
{
firstSelected->setOpen (false);
}
else
{
TreeViewItem* parent = firstSelected->parentItem;
moveSelectedRow (numPages);
currentItem = getSelectedItem (0);
if ((! rootItemVisible) && parent == rootItem)
parent = nullptr;
if (currentItem == nullptr)
break;
if (parent != nullptr)
{
parent->setSelected (true, true);
scrollToKeepItemVisible (parent);
}
}
}
}
else if (key.isKeyCode (KeyPress::rightKey))
{
TreeViewItem* const firstSelected = getSelectedItem (0);
const int y = currentItem->getItemPosition (false).getY();
if ((numPages < 0 && y <= targetY) || (numPages > 0 && y >= targetY))
break;
if (firstSelected != nullptr)
{
if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems())
moveSelectedRow (1);
else
firstSelected->setOpen (true);
const int newRow = currentItem->getRowNumberInTree();
if (newRow == currentRow)
break;
currentRow = newRow;
} }
} }
else
}
bool TreeView::keyPressed (const KeyPress& key)
{
if (rootItem != nullptr
&& ! key.getModifiers().testFlags (ModifierKeys::ctrlAltCommandModifiers))
{ {
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 void TreeView::itemsChanged() noexcept


+ 4
- 0
modules/juce_gui_basics/widgets/juce_TreeView.h View File

@@ -820,6 +820,10 @@ private:
void hideDragHighlight() noexcept; void hideDragHighlight() noexcept;
void handleDrag (const StringArray& files, const SourceDetails&); void handleDrag (const StringArray& files, const SourceDetails&);
void handleDrop (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); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeView);
}; };


+ 15
- 0
modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp View File

@@ -1425,3 +1425,18 @@ void CodeEditorComponent::State::restoreState (CodeEditorComponent& editor) cons
if (lastTopLine > 0 && lastTopLine < editor.getDocument().getNumLines()) if (lastTopLine > 0 && lastTopLine < editor.getDocument().getNumLines())
editor.scrollToLine (lastTopLine); 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);
}

+ 5
- 0
modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.h View File

@@ -163,11 +163,16 @@ public:
{ {
/** Creates an object containing the state of the given editor. */ /** Creates an object containing the state of the given editor. */
State (const CodeEditorComponent& 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; State (const State& other) noexcept;
/** Updates the given editor with this saved state. */ /** Updates the given editor with this saved state. */
void restoreState (CodeEditorComponent& editor) const; void restoreState (CodeEditorComponent& editor) const;
/** Returns a stringified version of this state that can be used to recreate it later. */
String toString() const;
private: private:
int lastTopLine, lastCaretPos, lastSelectionEnd; int lastTopLine, lastCaretPos, lastSelectionEnd;
}; };


Loading…
Cancel
Save