mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-13 04:42:12 +03:00
Fix in drop-down height calculation.
Added `--diff` parameter. Allow to load multiple files and folders from the CLI.
This commit is contained in:
@@ -32,7 +32,8 @@ class EE_API UIDiffView : public UIWidget {
|
||||
virtual bool isType( const Uint32& type ) const override;
|
||||
|
||||
void loadFromPatch( const std::string& patchText, const std::string& originalFilePath = "" );
|
||||
void loadFromStrings( const std::string& oldText, const std::string& newText );
|
||||
void loadFromStrings( const std::string& oldText, const std::string& newText,
|
||||
const std::string& originalFilePath = "" );
|
||||
void loadFromFile( const std::string& oldFilePath, const std::string& newFilePath );
|
||||
|
||||
UICodeEditor* getEditor() const { return mEditor; }
|
||||
@@ -110,6 +111,7 @@ class EE_API UIDiffView : public UIWidget {
|
||||
void updateButtonsText();
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Tools
|
||||
} // namespace Tools
|
||||
}} // namespace EE::UI
|
||||
|
||||
#endif // EE_UI_TOOLS_UIDIFFVIEW_HPP
|
||||
|
||||
@@ -790,7 +790,8 @@ void UIDiffView::loadFromPatch( const std::string& patchText,
|
||||
onSizeChange();
|
||||
}
|
||||
|
||||
void UIDiffView::loadFromStrings( const std::string& oldText, const std::string& newText ) {
|
||||
void UIDiffView::loadFromStrings( const std::string& oldText, const std::string& newText,
|
||||
const std::string& originalFilePath ) {
|
||||
mLines.clear();
|
||||
|
||||
std::vector<std::string> leftLines = String::split( oldText, '\n', true );
|
||||
@@ -828,9 +829,15 @@ void UIDiffView::loadFromStrings( const std::string& oldText, const std::string&
|
||||
computeSubLineDiff( oldLine, newLine );
|
||||
} );
|
||||
|
||||
mShowCompleteView = false;
|
||||
mCompleteViewToggle->setText( i18n( "diffview_complete", "Complete" ) );
|
||||
if ( !originalFilePath.empty() ) {
|
||||
auto def = SyntaxDefinitionManager::instance()->getByExtension( originalFilePath );
|
||||
mSyntaxDef =
|
||||
SyntaxDefinitionManager::instance()->getLanguageDefinition( def.getLanguageIndex() );
|
||||
mFileName = FileSystem::fileNameFromPath( originalFilePath );
|
||||
}
|
||||
|
||||
updateEditorsText();
|
||||
updateButtonsText();
|
||||
onSizeChange();
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ UIDropDownList* UIDropDownList::showList() {
|
||||
|
||||
Float height = std::ceil(
|
||||
std::ceil( eemin( mListBox->getItemsCount(), mStyleConfig.MaxNumVisibleItems ) *
|
||||
PixelDensity::pxToDp( mListBox->getRowHeight() ) ) +
|
||||
mListBox->getRowHeight() ) +
|
||||
tPadding.Top + tPadding.Bottom +
|
||||
( mListBox->getHorizontalScrollBar() &&
|
||||
mListBox->getHorizontalScrollBar()->isVisible() &&
|
||||
|
||||
@@ -2696,6 +2696,25 @@ void App::loadDiffFromPath( const std::string& path ) {
|
||||
diffView->setSyntaxColorScheme( *getCurrentColorScheme() );
|
||||
}
|
||||
|
||||
void App::loadDiffFromPaths( const std::string& oldPath, const std::string& newPath ) {
|
||||
auto diffViewTitle = i18n( "diff_viewer", "Diff Viewer" );
|
||||
auto* diffView = Tools::UIDiffView::New();
|
||||
auto [tab, iv] = mSplitter->createWidget( diffView, i18n( "diff_viewer", "Diff Viewer" ) );
|
||||
if ( !newPath.empty() ) {
|
||||
std::string fileName = FileSystem::fileNameFromPath( newPath );
|
||||
tab->setText( diffViewTitle + ": " + fileName );
|
||||
tab->setTooltipText( newPath );
|
||||
} else {
|
||||
tab->setText( diffViewTitle );
|
||||
}
|
||||
auto icon = findIcon( "filetype-diff" );
|
||||
tab->setIcon( icon ? icon : findIcon( "file" ) );
|
||||
|
||||
diffView->setHeadersVisible( true );
|
||||
diffView->loadFromFile( oldPath, newPath );
|
||||
diffView->setSyntaxColorScheme( *getCurrentColorScheme() );
|
||||
}
|
||||
|
||||
void App::openFileFromPath( const std::string& path ) {
|
||||
std::string ext = FileSystem::fileExtension( path );
|
||||
if ( !Image::isImageExtension( path ) && !SoundFileFactory::isKnownFileExtension( path ) &&
|
||||
@@ -3637,79 +3656,107 @@ void App::initProjectTreeViewUI() {
|
||||
mProjectTreeView->setAutoExpandOnSingleColumn( true );
|
||||
}
|
||||
|
||||
void App::initProjectTreeView( std::string path, bool openClean ) {
|
||||
void App::discardEmptyTab() {
|
||||
// If we opened a new tab and the first tab is simply empty, discard it
|
||||
if ( mSplitter->getTabWidgets().size() == 1 &&
|
||||
mSplitter->getTabWidgets()[0]->getTabCount() == 2 &&
|
||||
mSplitter->getTabWidgets()[0]->getTab( 0 ) ) {
|
||||
auto tab = mSplitter->getTabWidgets()[0]->getTab( 0 );
|
||||
if ( tab && tab->getOwnedWidget() && tab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
|
||||
auto editor = tab->getOwnedWidget()->asType<UICodeEditor>();
|
||||
if ( editor->hasDocument() && editor->getDocument().isEmpty() ) {
|
||||
mSplitter->getTabWidgets()[0]->removeTab( tab );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void App::initProjectTreeView( std::vector<std::string>&& paths, bool openClean ) {
|
||||
initProjectTreeViewUI();
|
||||
|
||||
bool hasPosition = pathHasPosition( path );
|
||||
TextPosition initialPosition;
|
||||
if ( hasPosition ) {
|
||||
auto pathAndPosition = getPathAndPosition( path );
|
||||
path = pathAndPosition.first;
|
||||
initialPosition = pathAndPosition.second;
|
||||
}
|
||||
const auto getInitialPosition = []( std::string& path ) -> TextPosition {
|
||||
bool hasPosition = pathHasPosition( path );
|
||||
TextPosition initialPosition;
|
||||
if ( hasPosition ) {
|
||||
auto pathAndPosition = getPathAndPosition( path );
|
||||
path = pathAndPosition.first;
|
||||
initialPosition = pathAndPosition.second;
|
||||
}
|
||||
return initialPosition;
|
||||
};
|
||||
|
||||
if ( !path.empty() ) {
|
||||
for ( auto& path : paths )
|
||||
path = FileSystem::expandTilde( path );
|
||||
|
||||
if ( FileSystem::isDirectory( path ) ) {
|
||||
loadFolder( path );
|
||||
} else if ( String::startsWith( path, "https://" ) ||
|
||||
String::startsWith( path, "http://" ) ) {
|
||||
loadFolder( "." );
|
||||
loadFileFromPath( path, false );
|
||||
} else {
|
||||
std::string rpath( FileSystem::getRealPath( path ) );
|
||||
std::string folderPath( FileSystem::fileRemoveFileName( rpath ) );
|
||||
if ( !paths.empty() ) {
|
||||
bool openedFolder = false;
|
||||
bool inNewTab = paths.size() != 1;
|
||||
|
||||
if ( FileSystem::isDirectory( folderPath ) ) {
|
||||
loadFileSystemMatcher( folderPath );
|
||||
for ( auto& path : paths ) {
|
||||
if ( FileSystem::isDirectory( path ) ) {
|
||||
loadFolder( path, openedFolder );
|
||||
openedFolder = true;
|
||||
} else if ( String::startsWith( path, "https://" ) ||
|
||||
String::startsWith( path, "http://" ) ) {
|
||||
if ( !openedFolder )
|
||||
loadFolder( "." );
|
||||
loadFileFromPath( path, inNewTab );
|
||||
} else {
|
||||
std::string rpath( FileSystem::getRealPath( paths[0] ) );
|
||||
std::string folderPath( FileSystem::fileRemoveFileName( rpath ) );
|
||||
|
||||
mFileSystemModel =
|
||||
FileSystemModel::New( folderPath, FileSystemModel::Mode::FilesAndDirectories,
|
||||
{ true,
|
||||
true,
|
||||
true,
|
||||
{},
|
||||
[this]( const std::string& filePath ) -> bool {
|
||||
return isFileVisibleInTreeView( filePath );
|
||||
} },
|
||||
&mUISceneNode->getTranslator(), mThreadPool );
|
||||
if ( !inNewTab && FileSystem::isDirectory( folderPath ) ) {
|
||||
loadFileSystemMatcher( folderPath );
|
||||
|
||||
mProjectTreeView->setModel( mFileSystemModel );
|
||||
mProjectViewEmptyCont->setVisible( false );
|
||||
mFileSystemModel = FileSystemModel::New(
|
||||
folderPath, FileSystemModel::Mode::FilesAndDirectories,
|
||||
{ true,
|
||||
true,
|
||||
true,
|
||||
{},
|
||||
[this]( const std::string& filePath ) -> bool {
|
||||
return isFileVisibleInTreeView( filePath );
|
||||
} },
|
||||
&mUISceneNode->getTranslator(), mThreadPool );
|
||||
|
||||
if ( mFileSystemListener )
|
||||
mFileSystemListener->setFileSystemModel( mFileSystemModel );
|
||||
mProjectTreeView->setModel( mFileSystemModel );
|
||||
mProjectViewEmptyCont->setVisible( false );
|
||||
|
||||
auto forcePosition = getForcePositionFn( initialPosition );
|
||||
auto onLoaded = [this, forcePosition]( UICodeEditor* codeEditor,
|
||||
const std::string& path ) {
|
||||
if ( forcePosition )
|
||||
forcePosition( codeEditor, path );
|
||||
syncProjectTreeWithEditor( mSplitter->getCurEditor() );
|
||||
};
|
||||
if ( mFileSystemListener )
|
||||
mFileSystemListener->setFileSystemModel( mFileSystemModel );
|
||||
|
||||
if ( FileSystem::fileExists( rpath ) ) {
|
||||
loadFileFromPath( rpath, false, nullptr, onLoaded );
|
||||
} else if ( FileSystem::fileCanWrite( folderPath ) ) {
|
||||
loadFileFromPath( rpath, false, nullptr, onLoaded );
|
||||
}
|
||||
auto forcePosition = getForcePositionFn( getInitialPosition( paths[0] ) );
|
||||
auto onLoaded = [this, forcePosition]( UICodeEditor* codeEditor,
|
||||
const std::string& path ) {
|
||||
if ( forcePosition )
|
||||
forcePosition( codeEditor, path );
|
||||
syncProjectTreeWithEditor( mSplitter->getCurEditor() );
|
||||
};
|
||||
|
||||
// If we opened a new tab and the first tab is simply empty, discard it
|
||||
if ( mSplitter->getTabWidgets().size() == 1 &&
|
||||
mSplitter->getTabWidgets()[0]->getTabCount() == 2 &&
|
||||
mSplitter->getTabWidgets()[0]->getTab( 0 ) ) {
|
||||
auto tab = mSplitter->getTabWidgets()[0]->getTab( 0 );
|
||||
if ( tab && tab->getOwnedWidget() &&
|
||||
tab->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
|
||||
auto editor = tab->getOwnedWidget()->asType<UICodeEditor>();
|
||||
if ( editor->hasDocument() && editor->getDocument().isEmpty() ) {
|
||||
mSplitter->getTabWidgets()[0]->removeTab( tab );
|
||||
}
|
||||
if ( FileSystem::fileExists( rpath ) ) {
|
||||
loadFileFromPath( rpath, false, nullptr, onLoaded );
|
||||
} else if ( FileSystem::fileCanWrite( folderPath ) ) {
|
||||
loadFileFromPath( rpath, false, nullptr, onLoaded );
|
||||
}
|
||||
|
||||
discardEmptyTab();
|
||||
|
||||
mSettings->updateProjectSettingsMenu();
|
||||
} else {
|
||||
auto forcePosition = getForcePositionFn( getInitialPosition( path ) );
|
||||
auto onLoaded = [this, forcePosition]( UICodeEditor* codeEditor,
|
||||
const std::string& path ) {
|
||||
if ( forcePosition )
|
||||
forcePosition( codeEditor, path );
|
||||
syncProjectTreeWithEditor( mSplitter->getCurEditor() );
|
||||
};
|
||||
|
||||
if ( FileSystem::fileExists( rpath ) ) {
|
||||
loadFileFromPath( rpath, inNewTab, nullptr, onLoaded );
|
||||
} else if ( FileSystem::fileCanWrite( folderPath ) ) {
|
||||
loadFileFromPath( rpath, inNewTab, nullptr, onLoaded );
|
||||
}
|
||||
}
|
||||
|
||||
mSettings->updateProjectSettingsMenu();
|
||||
}
|
||||
}
|
||||
} else if ( mConfig.workspace.restoreLastSession && !mRecentFolders.empty() && !openClean ) {
|
||||
@@ -4160,7 +4207,8 @@ void App::init( InitParameters& params ) {
|
||||
if ( params.prematureExit )
|
||||
return;
|
||||
|
||||
if ( !params.openClean && needsRedirectToRunningProcess( params.file ) )
|
||||
if ( !params.openClean && params.files.size() == 1 &&
|
||||
needsRedirectToRunningProcess( params.files[0] ) )
|
||||
return;
|
||||
|
||||
currentDisplay = displayManager->getDisplayIndex( mConfig.windowState.displayIndex <
|
||||
@@ -4793,7 +4841,7 @@ void App::init( InitParameters& params ) {
|
||||
params.file = "";
|
||||
#endif
|
||||
|
||||
if ( params.terminal && params.file.empty() && params.fileToOpen.empty() ) {
|
||||
if ( params.terminal && params.files.empty() && params.fileToOpen.empty() ) {
|
||||
mTerminalMode = true;
|
||||
mTerminalModeSidePanelWasVisible = mConfig.ui.showSidePanel;
|
||||
mConfig.ui.showSidePanel = false;
|
||||
@@ -4803,8 +4851,11 @@ void App::init( InitParameters& params ) {
|
||||
getSettingsMenu()->updateViewMenu();
|
||||
initProjectViewEmptyCont();
|
||||
mTerminalManager->createNewTerminal();
|
||||
} else if ( params.diff ) {
|
||||
loadDiffFromPaths( params.files[0], params.files[1] );
|
||||
discardEmptyTab();
|
||||
} else {
|
||||
initProjectTreeView( params.file, params.openClean );
|
||||
initProjectTreeView( std::move( params.files ), params.openClean );
|
||||
}
|
||||
|
||||
mFileToOpen = FileSystem::expandTilde( params.fileToOpen );
|
||||
@@ -4886,8 +4937,8 @@ using namespace ecode;
|
||||
EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
args::ArgumentParser parser( "ecode" );
|
||||
args::HelpFlag help( parser, "help", "Display this help menu", { 'h', '?', "help" } );
|
||||
args::Positional<std::string> fileOrFolderPos( parser, "file_or_folder",
|
||||
"The file or folder path to open" );
|
||||
args::PositionalList<std::string> fileOrFolderPos( parser, "file_or_folder",
|
||||
"The file/s or folder/s path to open" );
|
||||
args::ValueFlag<std::string> file(
|
||||
parser, "file",
|
||||
"The file path to open. A file path can also contain the line number and column to "
|
||||
@@ -4984,6 +5035,9 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
"the earliest launched instance instead of the most recently launched one.",
|
||||
{ "first-instance" } );
|
||||
|
||||
args::Flag diff( parser, "diff <OLD_PATH> <NEW_PATH>", "Pairs of file paths to diff.",
|
||||
{ "diff" } );
|
||||
|
||||
#ifdef EE_TEXT_SHAPER_ENABLED
|
||||
args::Flag textShaper( parser, "text-shaper",
|
||||
"WARNING: Do not use this option. It will be completely "
|
||||
@@ -5054,7 +5108,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
|
||||
App::InitParameters params;
|
||||
params.logLevel = logLevel.Get();
|
||||
params.file = folder ? folder.Get() : fileOrFolderPos.Get();
|
||||
params.files = folder ? std::vector<std::string>{ folder.Get() } : fileOrFolderPos.Get();
|
||||
params.pidelDensity = pixelDensityConf ? pixelDensityConf.Get() : 0.f;
|
||||
params.colorScheme = prefersColorScheme ? prefersColorScheme.Get() : "";
|
||||
params.terminal = terminal.Get();
|
||||
@@ -5073,6 +5127,26 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
params.profile = profile.Get();
|
||||
params.disablePlugins = disablePlugins.Get();
|
||||
params.redirectToFirstInstance = redirectToFirstInstance.Get();
|
||||
params.diff = diff.Get();
|
||||
|
||||
if ( params.diff ) {
|
||||
if ( params.files.size() != 2 ) {
|
||||
Sys::windowAttachConsole();
|
||||
std::cout << "error: 2 values required for '--diff <OLD_PATH> <NEW_PATH>' but "
|
||||
<< params.files.size() << " was provided" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < params.files.size(); i++ ) {
|
||||
if ( !FileSystem::fileExists( params.files[i] ) ||
|
||||
FileSystem::isDirectory( params.files[i] ) ) {
|
||||
Sys::windowAttachConsole();
|
||||
std::cout << "error: invalid parameter " << ( i + 1 )
|
||||
<< " for '--diff <OLD_PATH> <NEW_PATH>' " << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appInstance = eeNew( App, ( jobs, args ) );
|
||||
appInstance->init( params );
|
||||
|
||||
@@ -43,24 +43,25 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
|
||||
struct InitParameters {
|
||||
LogLevel logLevel{ LogLevel::Info };
|
||||
std::string file;
|
||||
std::vector<std::string> files;
|
||||
Float pidelDensity{ 0.f };
|
||||
std::string colorScheme;
|
||||
std::string css;
|
||||
std::string fileToOpen;
|
||||
std::string language;
|
||||
std::string profile;
|
||||
bool terminal{ false };
|
||||
bool frameBuffer{ false };
|
||||
bool benchmarkMode{ false };
|
||||
std::string css;
|
||||
std::string fileToOpen;
|
||||
bool stdOutLogs{ false };
|
||||
bool disableFileLogs{ false };
|
||||
bool openClean{ false };
|
||||
bool portable{ false };
|
||||
std::string language;
|
||||
bool incognito{ false };
|
||||
bool prematureExit{ false };
|
||||
std::string profile;
|
||||
bool disablePlugins{ false };
|
||||
bool redirectToFirstInstance{ false };
|
||||
bool diff{ false };
|
||||
};
|
||||
|
||||
void init( InitParameters& );
|
||||
@@ -558,6 +559,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
|
||||
void loadDiffFromPath( const std::string& path );
|
||||
|
||||
void loadDiffFromPaths( const std::string& oldPath, const std::string& newPath );
|
||||
|
||||
void loadDiffFromMemory( const std::string& content, const std::string& originalFilePath = "" );
|
||||
|
||||
void createAndShowRecentFolderPopUpMenu( Node* recentFoldersBut );
|
||||
@@ -759,7 +762,7 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
|
||||
void initProjectTreeViewUI();
|
||||
|
||||
void initProjectTreeView( std::string path, bool openClean );
|
||||
void initProjectTreeView( std::vector<std::string>&& paths, bool openClean );
|
||||
|
||||
void initImageView();
|
||||
|
||||
@@ -868,6 +871,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
std::string firstInstanceIndicatorPath() const;
|
||||
|
||||
void tintTitleBar();
|
||||
|
||||
void discardEmptyTab();
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -797,9 +797,9 @@ void DebuggerPlugin::buildSidePanelTab() {
|
||||
<vbox id="debugger_panel" lw="mp" lh="wc" padding="4dp">
|
||||
<vbox id="debugger_config_view" lw="mp" lh="wc">
|
||||
<TextView text="@string(debugger, Debugger)" font-size="15dp" focusable="false" />
|
||||
<DropDownList id="debugger_list" layout_width="mp" layout_height="wrap_content" margin-top="2dp" />
|
||||
<DropDownList id="debugger_list" layout_width="mp" layout_height="wrap_content" margin-top="2dp" menu-width-mode="expand-if-needed" />
|
||||
<TextView text="@string(debugger_configuration, Debugger Configuration)" focusable="false" margin-top="8dp" />
|
||||
<DropDownList id="debugger_conf_list" layout_width="mp" layout_height="wrap_content" margin-top="2dp" />
|
||||
<DropDownList id="debugger_conf_list" layout_width="mp" layout_height="wrap_content" margin-top="2dp" menu-width-mode="expand-if-needed" />
|
||||
<PushButton id="debugger_run_button" lw="mp" lh="wc" text="@string(debug, Debug)" margin-top="8dp" icon="icon(debug-alt, 12dp)" />
|
||||
<PushButton id="debugger_build_and_run_button" lw="mp" lh="wc" text="@string(build_and_debug, Build & Debug)" margin-top="8dp" icon="icon(debug-alt, 12dp)" />
|
||||
<hbox id="panel_debugger_buttons" lw="wc" lh="wc" layout_gravity="center_horizontal" visible="false" clip="none" margin-top="8dp">
|
||||
|
||||
@@ -1459,7 +1459,7 @@ void GitPlugin::buildSidePanelTab() {
|
||||
<StackWidget id="git_panel_stack" lw="mp" lh="0" lw8="1">
|
||||
<vbox id="git_branches" lw="mp" lh="wc">
|
||||
<hbox lw="mp" lh="wc" padding="4dp">
|
||||
<DropDownList id="git_repo" lw="0" lh="wc" lw8="1" />
|
||||
<DropDownList id="git_repo" lw="0" lh="wc" lw8="1" menu-width-mode="expand-if-needed" />
|
||||
<PushButton id="branch_pull" text="@string(git_pull, Pull)" tooltip="@string(pull_branch, Pull Branch)" text-as-fallback="true" icon="icon(repo-pull, 12dp)" margin-left="2dp" />
|
||||
<PushButton id="branch_push" text="@string(git_push, Push)" tooltip="@string(push_branch, Push Branch)" text-as-fallback="true" icon="icon(repo-push, 12dp)" margin-left="2dp" />
|
||||
<PushButton id="branch_add" text="@string(git_add_branch, Add Branch)" tooltip="@string(add_branch, Add Branch)" text-as-fallback="true" icon="icon(add, 12dp)" margin-left="2dp" />
|
||||
|
||||
@@ -148,6 +148,8 @@ class PluginContextProvider {
|
||||
|
||||
virtual void loadImageFromPath( const std::string& path ) = 0;
|
||||
|
||||
virtual void loadDiffFromPaths( const std::string& oldPath, const std::string& newPath ) = 0;
|
||||
|
||||
virtual void loadDiffFromPath( const std::string& path ) = 0;
|
||||
|
||||
virtual void loadDiffFromMemory( const std::string& content,
|
||||
|
||||
Reference in New Issue
Block a user