mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-31 02:26:29 +03:00
Integration of the diff/patch viewing and file comparison in ecode (SpartanJ/ecode#130).
This commit is contained in:
@@ -111,6 +111,10 @@ p, ol, ul, pre {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
li > p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,8 @@ class EE_API UIDiffView : public UIWidget {
|
||||
|
||||
virtual void onSizeChange() override;
|
||||
|
||||
virtual Uint32 onKeyDown( const KeyEvent& event ) override;
|
||||
|
||||
void createEditor( UICodeEditor*& editor, std::unique_ptr<UIDiffEditorPlugin>& plugin );
|
||||
void syncScroll( UICodeEditor* source, UICodeEditor* target, bool emitEvent = false );
|
||||
void updateModeButton();
|
||||
|
||||
@@ -838,6 +838,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
|
||||
void setDisableScrollInvalidation( bool disable ) { mDisableScrollInvalidation = disable; }
|
||||
|
||||
size_t getTotalVisibleLines() const;
|
||||
|
||||
protected:
|
||||
struct LastXOffset {
|
||||
TextPosition position{ 0, 0 };
|
||||
@@ -1170,8 +1172,6 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
|
||||
void drawLockedIcon( const Vector2f start );
|
||||
|
||||
size_t getTotalVisibleLines() const;
|
||||
|
||||
void invalidateLineWrapMaxWidth( bool force );
|
||||
|
||||
void findRegionsDelayed();
|
||||
|
||||
@@ -52,6 +52,10 @@ class EE_API UIScrollView : public UITouchDraggableWidget {
|
||||
|
||||
void setAnchorScroll( bool anchor );
|
||||
|
||||
void setEnableDefaultKeybindings( bool enable );
|
||||
|
||||
bool areDefaultKeybindingsEnabled() const { return mDefaultKeybindings; }
|
||||
|
||||
protected:
|
||||
ScrollViewType mViewType;
|
||||
ScrollBarMode mVScrollMode;
|
||||
@@ -64,6 +68,7 @@ class EE_API UIScrollView : public UITouchDraggableWidget {
|
||||
Uint32 mPosChangeCb;
|
||||
bool mAutoSetClipStep{ true };
|
||||
bool mAnchorScroll{ false };
|
||||
bool mDefaultKeybindings{ true };
|
||||
Sizef mLastScrollViewSize;
|
||||
Node* mParentRef{ nullptr };
|
||||
Uint32 mParentSizeChangeCb{ 0 };
|
||||
@@ -83,6 +88,8 @@ class EE_API UIScrollView : public UITouchDraggableWidget {
|
||||
|
||||
virtual void onSizePolicyChange();
|
||||
|
||||
virtual Uint32 onKeyDown( const KeyEvent& event );
|
||||
|
||||
void onValueChangeCb( const Event* Event );
|
||||
|
||||
void onScrollViewSizeChange( const Event* Event );
|
||||
|
||||
@@ -37,18 +37,7 @@ const Uint32& KeyEvent::getMod() const {
|
||||
}
|
||||
|
||||
Uint32 KeyEvent::getSanitizedMod() const {
|
||||
Uint32 mod = 0;
|
||||
if ( mMod & KEYMOD_CTRL )
|
||||
mod |= KEYMOD_CTRL;
|
||||
if ( mMod & KEYMOD_SHIFT )
|
||||
mod |= KEYMOD_SHIFT;
|
||||
if ( mMod & KEYMOD_META )
|
||||
mod |= KEYMOD_META;
|
||||
if ( mMod & KEYMOD_LALT )
|
||||
mod |= KEYMOD_LALT;
|
||||
if ( mMod & KEYMOD_RALT )
|
||||
mod |= KEYMOD_RALT;
|
||||
return mod;
|
||||
return mMod & KEYMOD_CTRL_SHIFT_ALT_META;
|
||||
}
|
||||
|
||||
TextInputEvent::TextInputEvent( Node* node, const Uint32& eventNum, const Uint32& chr,
|
||||
|
||||
@@ -300,6 +300,7 @@ UIIconTheme* IconManager::init( const std::string& iconThemeName, FontTrueType*
|
||||
{ "inspect", 0xebd1 },
|
||||
{ "link", 0xeb15 },
|
||||
{ "agent", 0xec67 },
|
||||
{ "diff", 0xeae1 },
|
||||
|
||||
} ) {
|
||||
iconTheme->add( UIGlyphIcon::New( icon.first, codIconFont, icon.second ) );
|
||||
|
||||
@@ -880,4 +880,33 @@ void UIDiffView::setHeadersVisible( bool visible ) {
|
||||
updateModeButton();
|
||||
}
|
||||
|
||||
Uint32 UIDiffView::onKeyDown( const KeyEvent& event ) {
|
||||
auto editor = mViewMode == ViewMode::Unified ? mEditor : mRightEditor;
|
||||
|
||||
const auto moveLinesOffset = [editor]( int numLines ) {
|
||||
Int64 curLine = static_cast<Int64>( editor->getVisibleLineRange().first );
|
||||
Int64 line = curLine + numLines;
|
||||
editor->scrollToVisibleIndex(
|
||||
std::clamp( line, (Int64)0, (Int64)editor->getTotalVisibleLines() ), false, true );
|
||||
};
|
||||
|
||||
if ( !event.getSanitizedMod() ) {
|
||||
if ( event.getKeyCode() == Window::KEY_PAGEDOWN ) {
|
||||
moveLinesOffset( editor->getViewPortLineCount().y );
|
||||
} else if ( event.getKeyCode() == Window::KEY_PAGEUP ) {
|
||||
moveLinesOffset( -editor->getViewPortLineCount().y );
|
||||
} else if ( event.getKeyCode() == Window::KEY_DOWN ) {
|
||||
moveLinesOffset( 1 );
|
||||
} else if ( event.getKeyCode() == Window::KEY_UP ) {
|
||||
moveLinesOffset( -1 );
|
||||
} else if ( event.getKeyCode() == Window::KEY_HOME ) {
|
||||
editor->scrollToVisibleIndex( 0, false, true );
|
||||
} else if ( event.getKeyCode() == Window::KEY_END ) {
|
||||
editor->scrollToVisibleIndex( (Int64)editor->getTotalVisibleLines(), false, true );
|
||||
}
|
||||
}
|
||||
|
||||
return UIWidget::onKeyDown( event );
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Tools
|
||||
|
||||
@@ -469,4 +469,31 @@ void UIScrollView::setAnchorScroll( bool anchor ) {
|
||||
mAnchorScroll = anchor;
|
||||
}
|
||||
|
||||
Uint32 UIScrollView::onKeyDown( const KeyEvent& event ) {
|
||||
if ( !mDefaultKeybindings || event.getSanitizedMod() )
|
||||
return UITouchDraggableWidget::onKeyDown( event );
|
||||
|
||||
if ( event.getKeyCode() == Window::KEY_UP ) {
|
||||
mVScroll->setValue( mVScroll->getValue() - mVScroll->getClickStep() );
|
||||
return 1;
|
||||
} else if ( event.getKeyCode() == Window::KEY_DOWN ) {
|
||||
mVScroll->setValue( mVScroll->getValue() + mVScroll->getClickStep() );
|
||||
return 1;
|
||||
} else if ( event.getKeyCode() == Window::KEY_PAGEDOWN ) {
|
||||
mVScroll->setValue( mVScroll->getValue() + mVScroll->getPageStep() );
|
||||
return 1;
|
||||
} else if ( event.getKeyCode() == Window::KEY_PAGEUP ) {
|
||||
mVScroll->setValue( mVScroll->getValue() - mVScroll->getPageStep() );
|
||||
return 1;
|
||||
} else if ( event.getKeyCode() == Window::KEY_HOME ) {
|
||||
mVScroll->setValue( mVScroll->getMinValue() );
|
||||
return 1;
|
||||
} else if ( event.getKeyCode() == Window::KEY_END ) {
|
||||
mVScroll->setValue( mVScroll->getMaxValue() );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return UITouchDraggableWidget::onKeyDown( event );
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -357,7 +357,7 @@ void App::onDocumentUndoRedo( UICodeEditor* editor, TextDocument& doc ) {
|
||||
onDocumentModified( editor, doc );
|
||||
}
|
||||
|
||||
void App::openFileDialog() {
|
||||
UIFileDialog* App::openFileDialog( bool registerEvents ) {
|
||||
UIFileDialog* dialog = UIFileDialog::New(
|
||||
UIFileDialog::DefaultFlags |
|
||||
( mConfig.ui.nativeFileDialogs ? UIFileDialog::UseNativeFileDialog : 0 ),
|
||||
@@ -366,14 +366,16 @@ void App::openFileDialog() {
|
||||
dialog->setTitle( i18n( "open_file", "Open File" ) );
|
||||
dialog->setCloseShortcut( KEY_ESCAPE );
|
||||
dialog->setSingleClickNavigation( mConfig.editor.singleClickNavigation );
|
||||
dialog->setAllowsMultiFileSelect( true );
|
||||
dialog->on( Event::OpenFile, [this]( const Event* event ) {
|
||||
auto files = event->getNode()->asType<UIFileDialog>()->getFullPaths();
|
||||
for ( const auto& file : files ) {
|
||||
mLastFileFolder = FileSystem::fileRemoveFileName( file );
|
||||
loadFileFromPath( file );
|
||||
}
|
||||
} );
|
||||
if ( registerEvents ) {
|
||||
dialog->setAllowsMultiFileSelect( true );
|
||||
dialog->on( Event::OpenFile, [this]( const Event* event ) {
|
||||
auto files = event->getNode()->asType<UIFileDialog>()->getFullPaths();
|
||||
for ( const auto& file : files ) {
|
||||
mLastFileFolder = FileSystem::fileRemoveFileName( file );
|
||||
loadFileFromPath( file );
|
||||
}
|
||||
} );
|
||||
}
|
||||
dialog->on( Event::OnWindowClose, [this]( const Event* ) {
|
||||
if ( App::instance() && mSplitter && mSplitter->getCurWidget() &&
|
||||
!SceneManager::instance()->isShuttingDown() )
|
||||
@@ -381,6 +383,7 @@ void App::openFileDialog() {
|
||||
} );
|
||||
dialog->center();
|
||||
dialog->show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
std::string App::getDefaultFileDialogFolder() const {
|
||||
@@ -1712,6 +1715,8 @@ void App::onTabCreated( UITab* tab, UIWidget* ) {
|
||||
menuAdd( "split_top", "Split Top", "split-vertical", "split-top" );
|
||||
menuAdd( "split_bottom", "Split Bottom", "split-vertical", "split-bottom" );
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
menuAdd( "open_containing_folder_in_fm", "Open Containing Folder in File Manager",
|
||||
"folder-open", "open-containing-folder" );
|
||||
|
||||
@@ -1728,6 +1733,12 @@ void App::onTabCreated( UITab* tab, UIWidget* ) {
|
||||
menuAdd( "open_in_new_window", "Open in New Window", "window", "open-in-new-window" );
|
||||
|
||||
menuAdd( "move_to_new_window", "Move to New Window", "window", "move-to-new-window" );
|
||||
|
||||
if ( !tab->isSelected() ) {
|
||||
menu->addSeparator();
|
||||
menuAdd( "compare_with_active_tab", "Compare with Active Tab", "diff",
|
||||
"compare-with-active-tab" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( tab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ||
|
||||
@@ -2715,6 +2726,18 @@ void App::loadDiffFromPaths( const std::string& oldPath, const std::string& newP
|
||||
diffView->setSyntaxColorScheme( *getCurrentColorScheme() );
|
||||
}
|
||||
|
||||
void App::loadDiffFromStrings( const std::string& str, const std::string& otherStr ) {
|
||||
auto diffViewTitle = i18n( "diff_viewer", "Diff Viewer" );
|
||||
auto* diffView = Tools::UIDiffView::New();
|
||||
auto [tab, iv] = mSplitter->createWidget( diffView, i18n( "diff_viewer", "Diff Viewer" ) );
|
||||
tab->setText( diffViewTitle );
|
||||
auto icon = findIcon( "filetype-diff" );
|
||||
tab->setIcon( icon ? icon : findIcon( "file" ) );
|
||||
diffView->setHeadersVisible( true );
|
||||
diffView->loadFromStrings( str, otherStr );
|
||||
diffView->setSyntaxColorScheme( *getCurrentColorScheme() );
|
||||
}
|
||||
|
||||
void App::openFileFromPath( const std::string& path ) {
|
||||
std::string ext = FileSystem::fileExtension( path );
|
||||
if ( !Image::isImageExtension( path ) && !SoundFileFactory::isKnownFileExtension( path ) &&
|
||||
@@ -3010,6 +3033,26 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
}
|
||||
}
|
||||
} );
|
||||
doc.setCommand( "compare-with-active-tab", [this] {
|
||||
if ( mSplitter->curEditorExistsAndFocused() && mSplitter->getCurEditor() ) {
|
||||
UICodeEditor* editor = mSplitter->getCurEditor();
|
||||
UICodeEditor* otherEditor = nullptr;
|
||||
auto tabWidget = mSplitter->getCurTabWidget();
|
||||
if ( tabWidget && tabWidget->getTabSelected() &&
|
||||
tabWidget->getTabSelected()->getOwnedWidget() != editor &&
|
||||
tabWidget->getTabSelected()->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
|
||||
otherEditor = mSplitter->getCurTabWidget()
|
||||
->getTabSelected()
|
||||
->getOwnedWidget()
|
||||
->asType<UICodeEditor>();
|
||||
}
|
||||
|
||||
if ( otherEditor ) {
|
||||
loadDiffFromStrings( editor->getDocument().getText().toUtf8(),
|
||||
otherEditor->getDocument().getText().toUtf8() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
registerUnlockedCommands( doc );
|
||||
|
||||
editor->on( Event::OnDocumentSave, [this]( const Event* event ) {
|
||||
@@ -3150,7 +3193,8 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
};
|
||||
|
||||
auto docLoaded = [this, editor, docChanged]( const Event* event ) {
|
||||
if ( editor->getDocument().getFileInfo().getExtension() == "svg" ) {
|
||||
auto ext = editor->getDocument().getFileInfo().getExtension();
|
||||
if ( ext == "svg" ) {
|
||||
editor->getDocument().setCommand(
|
||||
"show-image-preview", [this]( TextDocument::Client* client ) {
|
||||
loadImageFromMedium(
|
||||
@@ -3164,8 +3208,70 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
findIcon( "filetype-jpg" ) )
|
||||
->setId( "show-image-preview" );
|
||||
} );
|
||||
} else if ( ext == "md" || ext == "markdown" ) {
|
||||
editor->getDocument().setCommand(
|
||||
"show-markdown-preview", [this]( TextDocument::Client* client ) {
|
||||
auto doc = static_cast<UICodeEditor*>( client )->getDocumentRef();
|
||||
auto mdView = UIMarkdownView::New();
|
||||
mdView->loadFromString( doc->getText().toUtf8() );
|
||||
auto title = i18n( "markdown_preview_ellipsis", "Markdown Preview:" ) + " " +
|
||||
doc->getFilename();
|
||||
auto [tab, _] = getSplitter()->createWidget( mdView, title );
|
||||
tab->setIcon( findIcon( "filetype-md" ) );
|
||||
} );
|
||||
}
|
||||
|
||||
editor->getDocument().setCommand( "compare-to", [this]( TextDocument::Client* client ) {
|
||||
auto dialog = openFileDialog( false );
|
||||
auto editor = static_cast<UICodeEditor*>( client );
|
||||
dialog->on( Event::OpenFile, [this, editor]( const Event* event ) {
|
||||
if ( !getSplitter()->editorExists( editor ) )
|
||||
return;
|
||||
auto files = event->getNode()->asType<UIFileDialog>()->getFullPaths();
|
||||
if ( !files.empty() ) {
|
||||
if ( editor->isDirty() ) {
|
||||
std::string otherStr;
|
||||
if ( FileSystem::fileGet( files[0], otherStr ) ) {
|
||||
loadDiffFromStrings( editor->getDocument().getText().toUtf8(),
|
||||
otherStr );
|
||||
}
|
||||
} else {
|
||||
loadDiffFromPaths( editor->getDocument().getFilePath(), files[0] );
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
editor->getDocument().setCommand(
|
||||
"compare-with-clipboard", [this]( TextDocument::Client* client ) {
|
||||
auto editor = static_cast<UICodeEditor*>( client );
|
||||
loadDiffFromStrings( editor->getDocument().getText().toUtf8(),
|
||||
getWindow()->getClipboard()->getText() );
|
||||
} );
|
||||
|
||||
editor->on( Event::OnCreateContextMenu, [this]( const Event* event ) {
|
||||
auto editor = event->getNode()->asType<UICodeEditor>();
|
||||
auto ext = editor->getDocument().getFileInfo().getExtension();
|
||||
auto cevent = static_cast<const ContextMenuEvent*>( event );
|
||||
auto menu = cevent->getMenu();
|
||||
|
||||
UIPopUpMenu* compareMenu = UIPopUpMenu::New();
|
||||
compareMenu->add( i18n( "compare_to_ellipsis", "Compare to..." ) )
|
||||
->setId( "compare-to" );
|
||||
compareMenu->add( i18n( "compare_with_clipboard", "Compare with clipboard" ) )
|
||||
->setId( "compare-with-clipboard" );
|
||||
|
||||
menu->addSeparator();
|
||||
menu->addSubMenu( i18n( "compare", "Compare" ), findIcon( "diff" ), compareMenu );
|
||||
|
||||
if ( ext == "md" || ext == "markdown" ) {
|
||||
menu->addSeparator();
|
||||
menu->add( i18n( "show_markdown_preview", "Show Markdown Preview" ),
|
||||
findIcon( "filetype-md" ) )
|
||||
->setId( "show-markdown-preview" );
|
||||
}
|
||||
} );
|
||||
|
||||
docChanged( event );
|
||||
};
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
|
||||
void setAppTitle( const std::string& title );
|
||||
|
||||
void openFileDialog();
|
||||
UIFileDialog* openFileDialog( bool registerEvents = true );
|
||||
|
||||
std::string getDefaultFileDialogFolder() const;
|
||||
|
||||
@@ -563,6 +563,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
|
||||
void loadDiffFromMemory( const std::string& content, const std::string& originalFilePath = "" );
|
||||
|
||||
void loadDiffFromStrings( const std::string& str, const std::string& otherStr );
|
||||
|
||||
void createAndShowRecentFolderPopUpMenu( Node* recentFoldersBut );
|
||||
|
||||
void createAndShowRecentFilesPopUpMenu( Node* recentFilesBut );
|
||||
|
||||
Reference in New Issue
Block a user