diff --git a/src/main/java/tech/minediamond/vortex/config/AppModule.java b/src/main/java/tech/minediamond/vortex/config/AppModule.java index 3277615..c2b7f13 100644 --- a/src/main/java/tech/minediamond/vortex/config/AppModule.java +++ b/src/main/java/tech/minediamond/vortex/config/AppModule.java @@ -27,6 +27,7 @@ import tech.minediamond.vortex.service.appConfig.AppConfigService; import tech.minediamond.vortex.service.autoStart.MockAutoStartService; import tech.minediamond.vortex.service.autoStart.WindowsAutoStartService; +import tech.minediamond.vortex.service.search.SearchService; import tech.minediamond.vortex.service.ui.ShowStageListenerFactory; import tech.minediamond.vortex.service.autoStart.IAutoStartService; import tech.minediamond.vortex.service.i18n.I18nService; @@ -36,6 +37,7 @@ import tech.minediamond.vortex.service.ui.TrayMenuService; import tech.minediamond.vortex.service.ui.WindowAnimator; import tech.minediamond.vortex.service.uncaughtExceptionHandle.GlobalUncaughtExceptionHandlerService; +import tech.minediamond.vortex.ui.component.SearchResultCardFactory; import tech.minediamond.vortex.ui.controller.EditorPanel; import tech.minediamond.vortex.ui.controller.MainWindow; import tech.minediamond.vortex.ui.controller.SettingPanel; @@ -58,6 +60,7 @@ protected void configure() { bind(EditorPanel.class); bind(SettingPanel.class); bind(TrayMenuService.class); + bind(SearchService.class); bind(WindowAnimator.class).in(Scopes.SINGLETON); @@ -76,6 +79,6 @@ protected void configure() { // 告诉 Guice,这个工厂的实现是基于 ShowStageListenerFactory 接口 .build(ShowStageListenerFactory.class)); - + install(new FactoryModuleBuilder().build(SearchResultCardFactory.class)); } } diff --git a/src/main/java/tech/minediamond/vortex/model/search/EverythingResult.java b/src/main/java/tech/minediamond/vortex/model/fileData/FileData.java similarity index 72% rename from src/main/java/tech/minediamond/vortex/model/search/EverythingResult.java rename to src/main/java/tech/minediamond/vortex/model/fileData/FileData.java index 45c1a01..841a328 100644 --- a/src/main/java/tech/minediamond/vortex/model/search/EverythingResult.java +++ b/src/main/java/tech/minediamond/vortex/model/fileData/FileData.java @@ -17,19 +17,21 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -package tech.minediamond.vortex.model.search; +package tech.minediamond.vortex.model.fileData; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.Date; import java.util.Objects; @Getter @Setter -public class EverythingResult { - private ResultType type; +@ToString +public class FileData { + private FileType type; private String fileName; private String extension; private String fullPath; @@ -37,11 +39,11 @@ public class EverythingResult { private Date dateModified; private Date dateCreated; - public EverythingResult(){ + public FileData(){ } - public EverythingResult(ResultType type, String fileName, String extension, String fullPath, long size, Date dateModified, Date dateCreated) { + public FileData(FileType type, String fileName, String extension, String fullPath, long size, Date dateModified, Date dateCreated) { this.type = type; this.fileName = fileName; this.extension = extension; @@ -51,20 +53,19 @@ public EverythingResult(ResultType type, String fileName, String extension, Stri this.dateCreated = dateCreated; } - @Override - public String toString() { - return "EverythingResult{" + - "type=" + type + - ", fileName='" + fileName + '\'' + - ", fullPath='" + fullPath + '\'' + - '}'; + public String getParentPath(){ + return switch (type){ + case FILE-> fullPath.substring(0, fullPath.lastIndexOf('\\')); + case FOLDER-> fullPath; + }; } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - return Objects.equals(fullPath, ((EverythingResult) o).fullPath); + return Objects.equals(fullPath, ((FileData) o).fullPath); } @Override diff --git a/src/main/java/tech/minediamond/vortex/model/search/ResultType.java b/src/main/java/tech/minediamond/vortex/model/fileData/FileType.java similarity index 91% rename from src/main/java/tech/minediamond/vortex/model/search/ResultType.java rename to src/main/java/tech/minediamond/vortex/model/fileData/FileType.java index 9d6eff6..bcf3cc0 100644 --- a/src/main/java/tech/minediamond/vortex/model/search/ResultType.java +++ b/src/main/java/tech/minediamond/vortex/model/fileData/FileType.java @@ -17,9 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -package tech.minediamond.vortex.model.search; +package tech.minediamond.vortex.model.fileData; -public enum ResultType { +public enum FileType { FILE, FOLDER } diff --git a/src/main/java/tech/minediamond/vortex/model/ui/ContentPanel.java b/src/main/java/tech/minediamond/vortex/model/ui/ContentPanel.java index deff287..bad95ef 100644 --- a/src/main/java/tech/minediamond/vortex/model/ui/ContentPanel.java +++ b/src/main/java/tech/minediamond/vortex/model/ui/ContentPanel.java @@ -20,8 +20,9 @@ package tech.minediamond.vortex.model.ui; public enum ContentPanel { - EDITORPANEL("editorPanel.fxml"), - SETTINGPANEL("settingPanel.fxml"); + EDITOR_PANEL("editorPanel.fxml"), + SETTING_PANEL("settingPanel.fxml"), + SEARCH_PANEL("searchPanel.fxml"); private final String fileName; diff --git a/src/main/java/tech/minediamond/vortex/service/search/Everything3.java b/src/main/java/tech/minediamond/vortex/service/search/Everything3.java index 2fe1fe4..58483e2 100644 --- a/src/main/java/tech/minediamond/vortex/service/search/Everything3.java +++ b/src/main/java/tech/minediamond/vortex/service/search/Everything3.java @@ -41,7 +41,8 @@ public interface Everything3 extends StdCallLibrary { enum PropertyType { FILE_NAME(0), SIZE(2), - FULL_PATH(240); + FULL_PATH(240), + IS_FOLDER(269); final WinDef.DWORD ID; @@ -166,6 +167,16 @@ class EverythingResultList extends PointerType { */ void Everything3_GetResultPropertyTextW(EverythingResultList resultList, WinDef.DWORD result_index, WinDef.DWORD propertyID, char[] buffer, WinDef.DWORD filename_size_in_wchars); + /** + * 根据属性值获取结果的特定属性 + * + * @param resultList 结果列表句柄。 + * @param result_index 结果的从零开始的索引。 + * @param propertyID 需要获取的属性的属性值 + * @return 返回的属性信息 + */ + byte Everything3_GetResultPropertyBYTE(EverythingResultList resultList, WinDef.DWORD result_index, WinDef.DWORD propertyID); + /** * 使用给定的客户端和搜索状态执行搜索。 diff --git a/src/main/java/tech/minediamond/vortex/service/search/EverythingQueryBuilder.java b/src/main/java/tech/minediamond/vortex/service/search/EverythingQueryBuilder.java index ff87f36..6320174 100644 --- a/src/main/java/tech/minediamond/vortex/service/search/EverythingQueryBuilder.java +++ b/src/main/java/tech/minediamond/vortex/service/search/EverythingQueryBuilder.java @@ -20,7 +20,7 @@ package tech.minediamond.vortex.service.search; import tech.minediamond.vortex.model.search.EverythingQuery; -import tech.minediamond.vortex.model.search.EverythingResult; +import tech.minediamond.vortex.model.fileData.FileData; import tech.minediamond.vortex.model.search.SearchMode; import java.nio.file.Path; @@ -38,7 +38,7 @@ *
  • {@link #mode(SearchMode)} - 设置搜索模式(文件/文件夹/全部)
  • * *

    - * 构建完成后,通过{@code query()}发起请求,并返回一个{@code List} + * 构建完成后,通过{@code query()}发起请求,并返回一个{@code List} * * @see EverythingService */ @@ -106,7 +106,7 @@ private EverythingQuery build() { * * @return 搜索结果列表 */ - public List query() { + public List query() { if (query == null || query.trim().isEmpty()) { return Collections.emptyList(); } diff --git a/src/main/java/tech/minediamond/vortex/service/search/EverythingService.java b/src/main/java/tech/minediamond/vortex/service/search/EverythingService.java index 8a5e55b..94478f4 100644 --- a/src/main/java/tech/minediamond/vortex/service/search/EverythingService.java +++ b/src/main/java/tech/minediamond/vortex/service/search/EverythingService.java @@ -25,8 +25,9 @@ import com.sun.jna.WString; import com.sun.jna.platform.win32.WinDef; import lombok.extern.slf4j.Slf4j; +import tech.minediamond.vortex.model.fileData.FileType; import tech.minediamond.vortex.model.search.EverythingQuery; -import tech.minediamond.vortex.model.search.EverythingResult; +import tech.minediamond.vortex.model.fileData.FileData; import tech.minediamond.vortex.model.search.SearchMode; import java.io.IOException; @@ -49,7 +50,7 @@ * 使用示例: *

      * EverythingService service = injector.getInstance(EverythingServiceTest.class);
    - * List<EverythingResult> results = service.QueryBuilder()
    + * List<FileData> results = service.QueryBuilder()
      *     .searchFor("document")
      *     .inFolders(List.of(Path.of("C:/Users")))
      *     .mode(SearchMode.FILES_ONLY)
    @@ -57,7 +58,7 @@
      * 
    * * @see EverythingQueryBuilder - * @see EverythingResult + * @see FileData */ @Singleton @Slf4j @@ -150,7 +151,7 @@ public Everything3.EverythingClient LinkEverythingInstance() { return client; } - public List query(EverythingQuery query) { + public List query(EverythingQuery query) { // 防御性检查 if (client == null) { @@ -165,12 +166,12 @@ public List query(EverythingQuery query) { Everything3.EverythingSearchState searchState = null; Everything3.EverythingResultList resultList = null; - List results = new ArrayList<>(); + List results = new ArrayList<>(); try { // 创建和配置搜索条件 searchState = lib.Everything3_CreateSearchState(); if (searchState == null) { - log.error("创建搜索失败。"); + log.error("无法执行查询:创建搜索失败。"); } // 设置搜索关键字 String finalQueryString; @@ -180,6 +181,7 @@ public List query(EverythingQuery query) { lib.Everything3_AddSearchPropertyRequest(searchState, Everything3.PropertyType.FULL_PATH.getID()); lib.Everything3_AddSearchPropertyRequest(searchState, Everything3.PropertyType.SIZE.getID()); lib.Everything3_AddSearchPropertyRequest(searchState, Everything3.PropertyType.FILE_NAME.getID()); + lib.Everything3_AddSearchPropertyRequest(searchState, Everything3.PropertyType.IS_FOLDER.getID()); //生成搜索词字符串 String queryKeywords = "\"" + query.query() + "\""; @@ -220,24 +222,35 @@ public List query(EverythingQuery query) { char[] buffer = new char[MAX_PATH]; + WinDef.DWORD resultListindex = new WinDef.DWORD(); for (int i = 0; i < numResults.intValue(); i++) { - EverythingResult everythingResult = new EverythingResult(); + FileData fileData = new FileData(); + resultListindex.setValue(i); //获取搜索结果的完整路径 - lib.Everything3_GetResultPropertyTextW(resultList, new WinDef.DWORD(i), Everything3.PropertyType.FULL_PATH.getID(), buffer, new WinDef.DWORD(MAX_PATH)); + lib.Everything3_GetResultPropertyTextW(resultList, resultListindex, Everything3.PropertyType.FULL_PATH.getID(), buffer, new WinDef.DWORD(MAX_PATH)); String pathname = Native.toString(buffer); - everythingResult.setFullPath(pathname); + fileData.setFullPath(pathname); //获取搜索结果的名称 - lib.Everything3_GetResultPropertyTextW(resultList, new WinDef.DWORD(i), Everything3.PropertyType.FILE_NAME.getID(), buffer, new WinDef.DWORD(MAX_PATH)); + lib.Everything3_GetResultPropertyTextW(resultList, resultListindex, Everything3.PropertyType.FILE_NAME.getID(), buffer, new WinDef.DWORD(MAX_PATH)); String filename = Native.toString(buffer); - everythingResult.setFileName(filename); + fileData.setFileName(filename); //获取搜索结果的大小(单位:Byte) //这里直接将返回的无符号int64转换为long,但是考虑到无符号int64达到最大位需要文件8EB以上的大小,因此直接赋值问题不大 - long size = lib.Everything3_GetResultSize(resultList, new WinDef.DWORD(i)); - everythingResult.setSize(size); + long size = lib.Everything3_GetResultSize(resultList, resultListindex); + fileData.setSize(size); - results.add(everythingResult); + //获取文件的类型 + byte type = lib.Everything3_GetResultPropertyBYTE(resultList, resultListindex, Everything3.PropertyType.IS_FOLDER.getID()); + int intType = type & 0xFF; + if (intType != 0) { + fileData.setType(FileType.FOLDER); + } else { + fileData.setType(FileType.FILE); + } + + results.add(fileData); } } finally { if (resultList != null) { @@ -258,14 +271,14 @@ private String buildPathQueryPart(EverythingQuery query) { .map(Path::toString) .collect(Collectors.joining("|")); String pathQueryPart = "ancestor:" + body; - log.debug("pathQueryPart: {}",pathQueryPart); + log.debug("搜索路径关键词: {}",pathQueryPart); return pathQueryPart; } //构建搜索描述部分字符串 private String buildSearchModeQueryPart(EverythingQuery query) { SearchMode searchMode = query.searchMode().orElse(SearchMode.ALL); - log.debug("searchModeQueryPart: {}",searchMode.getQueryPrefix()); + log.debug("searchMode关键词: {}",searchMode.getQueryPrefix()); return searchMode.getQueryPrefix(); } diff --git a/src/main/java/tech/minediamond/vortex/service/search/SearchService.java b/src/main/java/tech/minediamond/vortex/service/search/SearchService.java new file mode 100644 index 0000000..3e4dd76 --- /dev/null +++ b/src/main/java/tech/minediamond/vortex/service/search/SearchService.java @@ -0,0 +1,114 @@ +/* + * Vortex + * Copyright (C) 2025 Mine-diamond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package tech.minediamond.vortex.service.search; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.concurrent.Service; +import javafx.concurrent.Task; +import lombok.extern.slf4j.Slf4j; +import tech.minediamond.vortex.model.fileData.FileData; +import tech.minediamond.vortex.model.search.SearchMode; +import tech.minediamond.vortex.service.i18n.I18nService; +import tech.minediamond.vortex.ui.component.ComponentList; +import tech.minediamond.vortex.ui.component.SearchResultCard; +import tech.minediamond.vortex.ui.component.SearchResultCardFactory; +import tech.minediamond.vortex.util.ClipboardUtil; +import tech.minediamond.vortex.util.OpenResourceUtil; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +@Slf4j +public class SearchService extends Service { + + private final String NAME = "Search Thread"; + + private final EverythingService everythingService; + private final I18nService i18n; + private final Injector injector; + private final StringProperty keyword = new SimpleStringProperty(); + + private final ThreadFactory searchThreadFactory; + private final ExecutorService executor; + + @Inject + public SearchService(EverythingService everythingService, I18nService i18n, Injector injector) { + this.everythingService = everythingService; + this.i18n = i18n; + this.injector = injector; + + searchThreadFactory = r -> { + Thread t = new Thread(r, NAME); + t.setDaemon(true); + return t; + }; + executor = Executors.newSingleThreadExecutor(searchThreadFactory); + setExecutor(executor); + + } + + public String getKeyword() { + return keyword.get(); + } + + public void search(String keyword) { + this.keyword.set(keyword); + restart(); + } + + @Override + protected Task createTask() { + return new Task() { + + @Override + protected ComponentList call() throws Exception { + List results = everythingService.QueryBuilder() + .mode(SearchMode.ALL) + .searchFor(keyword.get()) + .query(); + + ComponentList componentList = new ComponentList(); + + if (results.isEmpty()) { + updateProgress(0, 1); + return null; + } + + for (FileData result : results) { + SearchResultCard card = injector.getInstance(SearchResultCardFactory.class).create(result); + card.setOnOpen(OpenResourceUtil::OpenFile); + card.setOnRevealInFolder(OpenResourceUtil::OpenFileInFolder); + card.setOnCopy(fileData -> ClipboardUtil.copyToClipboard(fileData.getFullPath())); + card.setOnOpenPathInTerminal(OpenResourceUtil::OpenPathInTerminal); + componentList.addNode(card); + } + + log.info("搜索成功"); + return componentList; + } + }; + } + +} diff --git a/src/main/java/tech/minediamond/vortex/ui/component/SearchResultCard.java b/src/main/java/tech/minediamond/vortex/ui/component/SearchResultCard.java new file mode 100644 index 0000000..a5d3474 --- /dev/null +++ b/src/main/java/tech/minediamond/vortex/ui/component/SearchResultCard.java @@ -0,0 +1,196 @@ +/* + * Vortex + * Copyright (C) 2025 Mine-diamond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package tech.minediamond.vortex.ui.component; + +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.control.Button; +import javafx.scene.control.Control; +import javafx.scene.control.Label; +import javafx.scene.control.SkinBase; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import lombok.Getter; +import org.kordamp.ikonli.fluentui.FluentUiRegularAL; +import org.kordamp.ikonli.fluentui.FluentUiRegularMZ; +import org.kordamp.ikonli.javafx.FontIcon; +import tech.minediamond.vortex.model.fileData.FileData; +import tech.minediamond.vortex.service.i18n.I18nService; + +import java.util.function.Consumer; + +public class SearchResultCard extends Control { + + private final ObjectProperty> onOpen = new SimpleObjectProperty<>(); + private final ObjectProperty> onRevealInFolder = new SimpleObjectProperty<>(); + private final ObjectProperty> onCopy = new SimpleObjectProperty<>(); + private final ObjectProperty> onOpenPathInTerminal = new SimpleObjectProperty<>(); + + private final I18nService i18n; + + @Getter + private final FileData result; + + @Inject + public SearchResultCard(@Assisted FileData result, I18nService i18n) { + this.result = result; + this.i18n = i18n; + } + + @Override + protected Skin createDefaultSkin() { + return new Skin(this); + } + + public Consumer getOnOpen() { + return onOpen.get(); + } + + public void setOnOpen(Consumer action) { + onOpen.set(action); + } + + public ObjectProperty> onOpenProperty() { + return onOpen; + } + + public Consumer getOnRevealInFolder() { + return onRevealInFolder.get(); + } + + public void setOnRevealInFolder(Consumer action) { + onRevealInFolder.set(action); + } + + public ObjectProperty> onRevealInFolderProperty() { + return onRevealInFolder; + } + + public Consumer getOnCopy() { + return onCopy.get(); + } + + public void setOnCopy(Consumer action) { + onCopy.set(action); + } + + public ObjectProperty> onCopyProperty() { + return onCopy; + } + + public Consumer getOnOpenPathInTerminal() { + return onOpenPathInTerminal.get(); + } + + public void setOnOpenPathInTerminal(Consumer action) { + onOpenPathInTerminal.set(action); + } + + public ObjectProperty> onOpenPathInTerminalProperty() { + return onOpenPathInTerminal; + } + + public void open() { + Consumer c = getOnOpen(); + if (c != null) c.accept(result); + } + + public void revealInFolder() { + Consumer c = getOnRevealInFolder(); + if (c != null) c.accept(result); + } + + public void copy() { + Consumer c = getOnCopy(); + if (c != null) c.accept(result); + } + + public void openPathInTerminal() { + Consumer c = getOnOpenPathInTerminal(); + if (c != null) c.accept(result); + } + + private final class Skin extends SkinBase { + + private final FontIcon openInFolderIcon = new FontIcon(FluentUiRegularAL.FOLDER_24); + private final FontIcon openIcon = new FontIcon(FluentUiRegularMZ.OPEN_24); + private final FontIcon copyPathIcon = new FontIcon(FluentUiRegularAL.COPY_24); + private final FontIcon terminalIcon = new FontIcon(FluentUiRegularMZ.WINDOW_HORIZONTAL_20); + + HBox hBox = new HBox(); + VBox vbox = new VBox(); + + /** + * Constructor for all SkinBase instances. + * + * @param control The control for which this Skin should attach to. + */ + protected Skin(SearchResultCard control) { + super(control); + + hBox.getStyleClass().add("search-result-card"); + + Label fileNameLabel = new Label(control.result.getFileName()); + Label filePathLabel = new Label(control.result.getFullPath()); + fileNameLabel.getStyleClass().add("search-result-name-label"); + filePathLabel.getStyleClass().add("search-result-file-path"); + + Button openBtn = new Button(); + openBtn.setGraphic(openIcon); + openBtn.visibleProperty().bind(hBox.hoverProperty()); + openBtn.managedProperty().bind(hBox.hoverProperty()); + openBtn.setOnAction(e -> getSkinnable().open()); + SimpleHoverTooltip.textProperty(openBtn).set(i18n.t("file.open.tip")); + + Button openInFolderBtn = new Button(); + openInFolderBtn.setGraphic(openInFolderIcon); + openInFolderBtn.visibleProperty().bind(hBox.hoverProperty()); + openInFolderBtn.managedProperty().bind(hBox.hoverProperty()); + openInFolderBtn.setOnAction(e -> getSkinnable().revealInFolder()); + SimpleHoverTooltip.textProperty(openInFolderBtn).set(i18n.t("file.openInFolder.tip")); + + Button copyPathBtn = new Button(); + copyPathBtn.setGraphic(copyPathIcon); + copyPathBtn.visibleProperty().bind(hBox.hoverProperty()); + copyPathBtn.managedProperty().bind(hBox.hoverProperty()); + copyPathBtn.setOnAction(e -> getSkinnable().copy()); + SimpleHoverTooltip.textProperty(copyPathBtn).set(i18n.t("file.copyPath.tip")); + + Button openPathInTerminal = new Button(); + openPathInTerminal.setGraphic(terminalIcon); + openPathInTerminal.visibleProperty().bind(hBox.hoverProperty()); + openPathInTerminal.managedProperty().bind(hBox.hoverProperty()); + openPathInTerminal.setOnAction(e -> getSkinnable().openPathInTerminal()); + SimpleHoverTooltip.textProperty(openPathInTerminal).set(i18n.t("file.openPathInTerminal.tip")); + + Region region = new Region(); + HBox.setHgrow(region, Priority.ALWAYS); + + vbox.getChildren().addAll(fileNameLabel, filePathLabel); + hBox.getChildren().addAll(vbox, region, openBtn, openInFolderBtn, copyPathBtn, openPathInTerminal); + getChildren().add(hBox); + } + } + +} diff --git a/src/main/java/tech/minediamond/vortex/ui/component/SearchResultCardFactory.java b/src/main/java/tech/minediamond/vortex/ui/component/SearchResultCardFactory.java new file mode 100644 index 0000000..89812ba --- /dev/null +++ b/src/main/java/tech/minediamond/vortex/ui/component/SearchResultCardFactory.java @@ -0,0 +1,28 @@ +/* + * Vortex + * Copyright (C) 2025 Mine-diamond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package tech.minediamond.vortex.ui.component; + +import tech.minediamond.vortex.model.fileData.FileData; + +public interface SearchResultCardFactory { + + SearchResultCard create(FileData result); + +} diff --git a/src/main/java/tech/minediamond/vortex/ui/controller/MainWindow.java b/src/main/java/tech/minediamond/vortex/ui/controller/MainWindow.java index 40e98e0..ecaee1d 100644 --- a/src/main/java/tech/minediamond/vortex/ui/controller/MainWindow.java +++ b/src/main/java/tech/minediamond/vortex/ui/controller/MainWindow.java @@ -25,11 +25,14 @@ import com.google.inject.Injector; import javafx.application.Platform; import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.control.Button; +import javafx.scene.control.TextField; import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleGroup; import javafx.scene.image.Image; @@ -47,19 +50,14 @@ import tech.minediamond.vortex.model.appConfig.AppConfig; import tech.minediamond.vortex.model.ui.ContentPanel; import tech.minediamond.vortex.model.ui.Theme; -import tech.minediamond.vortex.service.ui.ShowStageListenerFactory; import tech.minediamond.vortex.service.i18n.I18nService; -import tech.minediamond.vortex.service.ui.AutoOperateService; -import tech.minediamond.vortex.service.ui.ShowStageListener; -import tech.minediamond.vortex.service.ui.StageProvider; -import tech.minediamond.vortex.service.ui.WindowAnimator; +import tech.minediamond.vortex.service.ui.*; import tech.minediamond.vortex.ui.component.SimpleHoverTooltip; import tech.minediamond.vortex.util.BindingUtils; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import static tech.minediamond.vortex.model.ui.Theme.*; @@ -71,24 +69,30 @@ public class MainWindow { private final I18nService i18n; private final AutoOperateService autoOperateService; - private static ContentPanel currentContentPanel; - @FXML private AnchorPane mainWindow; @FXML private AnchorPane tabWindow; @FXML + private TextField searchField; + @FXML private ToggleButton pinBtn; @FXML private ToggleGroup mainToggleGroup; @FXML private ToggleButton quickEditBtn; @FXML + private ToggleButton searchBtn; + @FXML + private ToggleButton settingBtn; + @FXML private Button themeSwitchBtn; @FXML private Button hideWindowBtn; //缓存已经加载的视图 private final Map viewCache = new HashMap<>(); + private final ObjectProperty currentContentPanelProperty = new SimpleObjectProperty<>(ContentPanel.EDITOR_PANEL); + private SearchPanel searchPanel; private double xOffset = 0; private double yOffset = 0; @@ -122,7 +126,7 @@ public void initialize() { handleDragWindow(); initUIComponent(); - loadOrGetView(ContentPanel.EDITORPANEL); + loadOrGetView(currentContentPanelProperty.get()); mainToggleGroup.selectToggle(quickEditBtn); } @@ -183,8 +187,27 @@ public void initUIComponent() { mainToggleGroup.selectToggle(oldValue); } }); + + currentContentPanelProperty.addListener((observable, oldValue, newValue) -> { + loadOrGetView(newValue); + switch (newValue) { + case EDITOR_PANEL -> mainToggleGroup.selectToggle(quickEditBtn); + case SETTING_PANEL -> mainToggleGroup.selectToggle(settingBtn); + case SEARCH_PANEL -> mainToggleGroup.selectToggle(searchBtn); + } + }); + + searchField.textProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null && !newValue.isEmpty()) { + currentContentPanelProperty.set(ContentPanel.SEARCH_PANEL); + searchPanel.search(newValue); + } else if (newValue.isEmpty()) { + searchPanel.searchClear(); + } + }); } + /** * 设置主窗口的属性 */ @@ -246,10 +269,6 @@ public void setupWindowListeners() { * @param fxmlFileName 文件名 */ private void loadOrGetView(ContentPanel fxmlFileName) { - if (fxmlFileName == currentContentPanel) { - log.info("原页面:{},新页面:{},页面一致", fxmlFileName.getFileName(), currentContentPanel.getFileName()); - return; - } String fileName = fxmlFileName.getFileName(); Parent view = viewCache.get(fileName); @@ -260,31 +279,36 @@ private void loadOrGetView(ContentPanel fxmlFileName) { loader.setResources(injector.getInstance(I18nService.class).getResourceBundle()); view = loader.load(); viewCache.put(fileName, view); // 加载后放入缓存 + if (fxmlFileName == ContentPanel.SEARCH_PANEL) { + searchPanel = loader.getController(); + } // 让新视图充满 tabWindow AnchorPane.setTopAnchor(view, 0.0); AnchorPane.setBottomAnchor(view, 0.0); AnchorPane.setLeftAnchor(view, 0.0); AnchorPane.setRightAnchor(view, 0.0); - log.info("原页面:{},新页面:{},从文件加载新页面", Optional.ofNullable(currentContentPanel).map(ContentPanel::getFileName).orElse("无"), fxmlFileName.getFileName()); + log.info("加载新页面:{},从文件加载新页面", fxmlFileName.getFileName()); } catch (IOException e) { log.error("加载 {} 页面出现错误: ", fileName, e); return; } } else { - log.info("原页面:{},新页面:{},从缓存加载新页面", Optional.ofNullable(currentContentPanel).map(ContentPanel::getFileName).orElse("无"), fxmlFileName.getFileName()); + log.info("加载新页面:{},从缓存加载新页面", fxmlFileName.getFileName()); } - currentContentPanel = fxmlFileName; //更新tabWindow tabWindow.getChildren().setAll(view); } public void showEditorPanel(ActionEvent actionEvent) { - loadOrGetView(ContentPanel.EDITORPANEL); + currentContentPanelProperty.set(ContentPanel.EDITOR_PANEL); } public void showSettingPanel(ActionEvent actionEvent) { - loadOrGetView(ContentPanel.SETTINGPANEL); + currentContentPanelProperty.set(ContentPanel.SETTING_PANEL); } + public void showSearchPanel(ActionEvent actionEvent) { + currentContentPanelProperty.set(ContentPanel.SEARCH_PANEL); + } } diff --git a/src/main/java/tech/minediamond/vortex/ui/controller/SearchPanel.java b/src/main/java/tech/minediamond/vortex/ui/controller/SearchPanel.java new file mode 100644 index 0000000..9f0a948 --- /dev/null +++ b/src/main/java/tech/minediamond/vortex/ui/controller/SearchPanel.java @@ -0,0 +1,114 @@ +/* + * Vortex + * Copyright (C) 2025 Mine-diamond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package tech.minediamond.vortex.ui.controller; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import javafx.animation.PauseTransition; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.fxml.FXML; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.HBox; +import javafx.util.Duration; +import lombok.extern.slf4j.Slf4j; +import tech.minediamond.vortex.service.i18n.I18nService; +import tech.minediamond.vortex.service.search.SearchService; + +@Singleton +@Slf4j +public class SearchPanel { + + @FXML + private ScrollPane scrollPane; + + private final PauseTransition debounce = new PauseTransition(Duration.millis(300)); + private String keyword; + + private final SearchService searchService; + private final I18nService i18n; + + ObjectProperty searchStatusProperty = new SimpleObjectProperty<>(); + HBox searchTiphbox = new HBox(); + HBox searchNotFoundTiphbox = new HBox(); + + enum SearchStatus { + SEARCHING, PENDING,NOT_FOUND + } + + @Inject + public SearchPanel(SearchService searchService, I18nService i18n) { + this.searchService = searchService; + this.i18n = i18n; + + debounce.setOnFinished(event -> { + log.info("开始搜索"); + searchService.search(keyword); + }); + + } + + public void initialize() { + scrollPane.contentProperty().bind(searchService.valueProperty()); + + Label searchtipLabel = new Label(i18n.t("search.pending.text")); + searchTiphbox.getChildren().add(searchtipLabel); + searchTiphbox.setAlignment(Pos.CENTER); + + Label searchNotFoundTipLabel = new Label(i18n.t("search.result.notFound.text")); + searchNotFoundTiphbox.getChildren().add(searchNotFoundTipLabel); + searchNotFoundTiphbox.setAlignment(Pos.CENTER); + + searchStatusProperty.addListener((observable, oldValue, newValue) -> {//监控不同的状态展示不同的界面 + switch (newValue) { + case PENDING -> { + scrollPane.contentProperty().unbind(); + scrollPane.contentProperty().set(searchTiphbox); + } + case NOT_FOUND -> { + scrollPane.contentProperty().unbind(); + scrollPane.contentProperty().set(searchNotFoundTiphbox); + } + case SEARCHING -> {scrollPane.contentProperty().bind(searchService.valueProperty());} + } + }); + searchStatusProperty.set(SearchStatus.PENDING); + + searchService.progressProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.equals(0.0)) { + searchStatusProperty.set(SearchStatus.NOT_FOUND); + } + }); + } + + public void search(String keyword) { + log.debug("即将搜索"); + searchStatusProperty.set(SearchStatus.SEARCHING); + this.keyword = keyword; + debounce.playFromStart(); + } + + public void searchClear(){ + searchStatusProperty.set(SearchStatus.PENDING); + } + +} diff --git a/src/main/java/tech/minediamond/vortex/util/ClipboardUtil.java b/src/main/java/tech/minediamond/vortex/util/ClipboardUtil.java new file mode 100644 index 0000000..6c80286 --- /dev/null +++ b/src/main/java/tech/minediamond/vortex/util/ClipboardUtil.java @@ -0,0 +1,54 @@ +/* + * Vortex + * Copyright (C) 2025 Mine-diamond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package tech.minediamond.vortex.util; + +import lombok.extern.slf4j.Slf4j; + +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +@Slf4j +public class ClipboardUtil { + /** + * 将指定的字符串复制到系统剪贴板。 + * + * @param text 要复制的字符串。 + */ + public static void copyToClipboard(String text) { + try { + // 1. 获取系统剪贴板 + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + + // 2. 创建一个 StringSelection 对象,它封装了要传输的字符串 + StringSelection stringSelection = new StringSelection(text); + + // 3. 将 StringSelection 对象放入剪贴板 + clipboard.setContents(stringSelection, null); + + log.info("成功将内容复制到剪贴板: \"{}\"", text); + + } catch (HeadlessException e) { + log.error("无法访问剪贴板。", e); + } catch (Exception e) { + log.error("复制到剪贴板时发生错误。", e); + } + } +} diff --git a/src/main/java/tech/minediamond/vortex/util/OpenResourceUtil.java b/src/main/java/tech/minediamond/vortex/util/OpenResourceUtil.java index ab9c958..018820b 100644 --- a/src/main/java/tech/minediamond/vortex/util/OpenResourceUtil.java +++ b/src/main/java/tech/minediamond/vortex/util/OpenResourceUtil.java @@ -20,7 +20,7 @@ package tech.minediamond.vortex.util; import lombok.extern.slf4j.Slf4j; -import tech.minediamond.vortex.model.search.EverythingResult; +import tech.minediamond.vortex.model.fileData.FileData; import java.awt.*; import java.io.File; @@ -33,7 +33,7 @@ public class OpenResourceUtil { private static final Desktop desktop = Desktop.getDesktop();; - public static boolean OpenFile(EverythingResult result) { + public static boolean OpenFile(FileData result) { if (desktop.isSupported(Desktop.Action.OPEN)) { try { desktop.open(new File(result.getFullPath())); @@ -46,4 +46,31 @@ public static boolean OpenFile(EverythingResult result) { } return false; } + + public static boolean OpenFileInFolder(FileData result) { + + ProcessBuilder pb = new ProcessBuilder("explorer","/select,"+"\""+result.getFullPath()+"\""); + pb.redirectErrorStream(true); + pb.redirectOutput(ProcessBuilder.Redirect.DISCARD); + try { + pb.start(); + return true; + } catch (IOException e) { + log.error("打开文件 {} 出现错误,文件路径:{}",result.getFileName(),result.getFullPath(),e); + } + return false; + } + + public static boolean OpenPathInTerminal(FileData result) { + ProcessBuilder pb = new ProcessBuilder("wt.exe", "-d", result.getParentPath()); + pb.redirectErrorStream(true); + pb.redirectOutput(ProcessBuilder.Redirect.DISCARD); + try { + pb.start(); + return true; + } catch (IOException e) { + log.error("在控制台打开文件 {} 出现错误,文件路径:{}",result.getFileName(),result.getFullPath(),e); + } + return true; + } } diff --git a/src/main/resources/lang/I18N.properties b/src/main/resources/lang/I18N.properties index 7d20700..2322c21 100644 --- a/src/main/resources/lang/I18N.properties +++ b/src/main/resources/lang/I18N.properties @@ -36,9 +36,16 @@ window.unpin=unpin mainWindow.tab.search=search mainWindow.tab.quickEdit=quick edit mainWindow.tab.setting=setting -search.text=search box +search.promptText=search box setting.startOnBoot.label=start on boot alert.exit.title=error alert.exit.headText=System not supported -alert.exit.contentText=Vortex only supports running on Windows systems\nIt does not support running on Linux, Mac, or other\nsystems \ No newline at end of file +alert.exit.contentText=Vortex only supports running on Windows systems\nIt does not support running on Linux, Mac, or other\nsystems +search.pending.text=Type text to search +search.result.notFound.text=No results found, try searching with a different keyword + +file.open.tip=open +file.openInFolder.tip=show in Folder +file.copyPath.tip=copy File Path +file.openPathInTerminal.tip=open Path in Console \ No newline at end of file diff --git a/src/main/resources/lang/I18N_en.properties b/src/main/resources/lang/I18N_en.properties index b87717e..447587d 100644 --- a/src/main/resources/lang/I18N_en.properties +++ b/src/main/resources/lang/I18N_en.properties @@ -37,8 +37,14 @@ window.unpin=unpin mainWindow.tab.search=search mainWindow.tab.quickEdit=quick edit mainWindow.tab.setting=setting -search.text=search box +search.promptText=search box setting.startOnBoot.label=start on boot alert.exit.title=error alert.exit.headText=System not supported -alert.exit.contentText=Vortex only supports running on Windows systems\nIt does not support running on Linux, Mac, or other\nsystems \ No newline at end of file +alert.exit.contentText=Vortex only supports running on Windows systems\nIt does not support running on Linux, Mac, or other\nsystems +search.pending.text=Type text to search +search.result.notFound.text=No results found, try searching with a different keyword +file.open.tip=open +file.openInFolder.tip=show in Folder +file.copyPath.tip=copy File Path +file.openPathInTerminal.tip=open Path in Console \ No newline at end of file diff --git a/src/main/resources/lang/I18N_zh_CN.properties b/src/main/resources/lang/I18N_zh_CN.properties index 18ea0bb..dda7394 100644 --- a/src/main/resources/lang/I18N_zh_CN.properties +++ b/src/main/resources/lang/I18N_zh_CN.properties @@ -37,8 +37,14 @@ window.unpin=\u672A\u56FA\u5B9A mainWindow.tab.search=\u641C\u7D22 mainWindow.tab.quickEdit=\u5FEB\u901F\u7F16\u8F91 mainWindow.tab.setting=\u8BBE\u7F6E -search.text=\u641C\u7D22\u6846 +search.promptText=\u641C\u7D22\u6846 setting.startOnBoot.label=\u5F00\u673A\u81EA\u542F\u52A8 alert.exit.title=\u9519\u8BEF alert.exit.headText=\u7CFB\u7EDF\u4E0D\u652F\u6301 -alert.exit.contentText=Vortex \u4EC5\u652F\u6301\u5728 Windows \u7CFB\u7EDF\u4E0A\u8FD0\u884C\n\u4E0D\u652F\u6301\u5728 Linux\u3001Mac \u6216\u5176\u4ED6\u7CFB\u7EDF\u4E0A\u8FD0\u884C \ No newline at end of file +alert.exit.contentText=Vortex \u4EC5\u652F\u6301\u5728 Windows \u7CFB\u7EDF\u4E0A\u8FD0\u884C\n\u4E0D\u652F\u6301\u5728 Linux\u3001Mac \u6216\u5176\u4ED6\u7CFB\u7EDF\u4E0A\u8FD0\u884C +search.pending.text=\u952E\u5165\u6587\u672C\u4EE5\u641C\u7D22 +search.result.notFound.text=\u6CA1\u627E\u5230\u4EFB\u4F55\u7ED3\u679C\uFF0C\u5C1D\u8BD5\u6362\u4E00\u4E2A\u5173\u952E\u8BCD\u641C\u7D22 +file.open.tip=\u6253\u5F00 +file.openInFolder.tip=\u5728\u6587\u4EF6\u5939\u4E2D\u663E\u793A +file.copyPath.tip=\u590D\u5236\u6587\u4EF6\u8DEF\u5F84 +file.openPathInTerminal.tip=\u5728\u63A7\u5236\u53F0\u4E2D\u6253\u5F00\u8DEF\u5F84 \ No newline at end of file diff --git a/src/main/resources/lang/I18N_zh_TW.properties b/src/main/resources/lang/I18N_zh_TW.properties index 83951b4..ecc3109 100644 --- a/src/main/resources/lang/I18N_zh_TW.properties +++ b/src/main/resources/lang/I18N_zh_TW.properties @@ -37,8 +37,14 @@ window.unpin=\u672A\u91D8\u9078 mainWindow.tab.search=\u641C\u5C0B mainWindow.tab.quickEdit=\u5FEB\u901F\u7DE8\u8F2F mainWindow.tab.setting=\u8A2D\u5B9A -search.text=\u641C\u5C0B\u6846 +search.promptText=\u641C\u5C0B\u6846 setting.startOnBoot.label=\u958B\u6A5F\u81EA\u555F\u52D5 alert.exit.title=\u932F\u8AA4 alert.exit.headText=\u7CFB\u7D71\u4E0D\u652F\u63F4 -alert.exit.contentText=Vortex \u50C5\u652F\u63F4\u5728 Windows \u7CFB\u7D71\u4E0A\u57F7\u884C\n\u4E0D\u652F\u63F4\u5728 Linux\u3001Mac \u6216\u5176\u4ED6\u7CFB\u7D71\u4E0A\u57F7\u884C \ No newline at end of file +alert.exit.contentText=Vortex \u50C5\u652F\u63F4\u5728 Windows \u7CFB\u7D71\u4E0A\u57F7\u884C\n\u4E0D\u652F\u63F4\u5728 Linux\u3001Mac \u6216\u5176\u4ED6\u7CFB\u7D71\u4E0A\u57F7\u884C +search.pending.text=\u9375\u5165\u6587\u5B57\u4EE5\u641C\u5C0B +search.result.notFound.text=\u6C92\u627E\u5230\u4EFB\u4F55\u7D50\u679C\uFF0C\u5617\u8A66\u63DB\u4E00\u500B\u95DC\u9375\u8A5E\u641C\u5C0B +file.open.tip=\u958B\u555F +file.openInFolder.tip=\u5728\u8CC7\u6599\u593E\u4E2D\u986F\u793A +file.copyPath.tip=\u8907\u88FD\u6A94\u6848\u8DEF\u5F91 +file.openPathInTerminal.tip=\u5728\u63A7\u5236\u53F0\u4E2D\u958B\u555F\u8DEF\u5F91 \ No newline at end of file diff --git a/src/main/resources/tech/minediamond/vortex/css/dark-theme.css b/src/main/resources/tech/minediamond/vortex/css/dark-theme.css index 8ffc65f..2b7638a 100644 --- a/src/main/resources/tech/minediamond/vortex/css/dark-theme.css +++ b/src/main/resources/tech/minediamond/vortex/css/dark-theme.css @@ -67,6 +67,10 @@ -fx-setting-combo-box-popup-bg-color-pressed: #5f5f5f;/*设置条目单选按钮弹出框按下时背景颜色*/ -fx-setting-combo-box-arrow-border-color: #e0e0e0;/* 设置条目单选按钮箭头边框颜色*/ + /*搜索面板样式*/ + -fx-search-result-file-path-text-color: #cdcdcd;/*搜索面板文件路径文本颜色*/ + -fx-search-result-card-bg-color-hover:#474747;/*搜索面板列表悬浮时背景颜色*/ + /*特殊样式*/ -fx-exit-button-bg-color-hover:#b34646;/*退出按钮悬浮时背景颜色*/ -fx-exit-button-bg-color-pressed: #c64d4d;/*退出按钮悬浮时背景颜色*/ diff --git a/src/main/resources/tech/minediamond/vortex/css/fluent-style.css b/src/main/resources/tech/minediamond/vortex/css/fluent-style.css index 2b52350..39c12c4 100644 --- a/src/main/resources/tech/minediamond/vortex/css/fluent-style.css +++ b/src/main/resources/tech/minediamond/vortex/css/fluent-style.css @@ -75,6 +75,10 @@ -fx-setting-combo-box-popup-bg-color-pressed: #b9b9be;/*设置条目单选按钮弹出框按下时背景颜色*/ -fx-setting-combo-box-arrow-border-color: #353333;/* 设置条目单选按钮箭头边框颜色*/ + /*搜索面板样式*/ + -fx-search-result-file-path-text-color: #cdcdcd;/*搜索面板文件路径文本颜色*/ + -fx-search-result-card-bg-color-hover:#474747;/*搜索面板列表悬浮时背景颜色*/ + /*特殊样式*/ -fx-exit-button-bg-color-hover: #f86868;/*退出按钮悬浮时背景颜色*/ -fx-exit-button-bg-color-pressed: #e86363;/*退出按钮悬浮时背景颜色*/ @@ -392,6 +396,38 @@ } +/* ===搜索结果卡片=== */ + +.search-result-card { + -fx-min-height: 50; + -fx-alignment: CENTER_LEFT; + -fx-background-radius: 4px; /* 圆角 */ + -fx-border-radius: 4px; /* 边框也需要圆角 */ + -fx-spacing: 2; + -fx-padding: 5 5 5 5; +} + +.search-result-card:hover { + -fx-background-color: -fx-search-result-card-bg-color-hover; +} + +.search-result-card .search-result-file-path { + -fx-text-fill: -fx-search-result-file-path-text-color; + -fx-font-size: 11px; +} + +.search-result-card .button{ + -fx-min-width: 35; + -fx-pref-height: 30; +} + +.search-result-card .button:hover{ + -fx-background-color: -fx-setting-list-button-bg-color-hover; +} + +.search-result-card .button:pressed{ + -fx-background-color: -fx-setting-list-button-bg-color-pressed; +} /* ===特殊按钮=== */ #pinBtn:selected .ikonli-font-icon{ diff --git a/src/main/resources/tech/minediamond/vortex/css/light-theme.css b/src/main/resources/tech/minediamond/vortex/css/light-theme.css index a8cc6fc..b224c1e 100644 --- a/src/main/resources/tech/minediamond/vortex/css/light-theme.css +++ b/src/main/resources/tech/minediamond/vortex/css/light-theme.css @@ -67,6 +67,10 @@ -fx-setting-combo-box-popup-bg-color-pressed: #b9b9be;/*设置条目单选按钮弹出框按下时背景颜色*/ -fx-setting-combo-box-arrow-border-color: #353333;/* 设置条目单选按钮箭头边框颜色*/ + /*搜索面板样式*/ + -fx-search-result-file-path-text-color: #636363;/*搜索面板文件路径文本颜色*/ + -fx-search-result-card-bg-color-hover:#d3d3d3;/*搜索面板列表悬浮时背景颜色*/ + /*特殊样式*/ -fx-exit-button-bg-color-hover: #f86868;/*退出按钮悬浮时背景颜色*/ -fx-exit-button-bg-color-pressed: #e86363;/*退出按钮悬浮时背景颜色*/ diff --git a/src/main/resources/tech/minediamond/vortex/ui/main-window.fxml b/src/main/resources/tech/minediamond/vortex/ui/main-window.fxml index e9ea5ce..a95e07c 100644 --- a/src/main/resources/tech/minediamond/vortex/ui/main-window.fxml +++ b/src/main/resources/tech/minediamond/vortex/ui/main-window.fxml @@ -34,7 +34,7 @@ - + @@ -42,7 +42,7 @@ - + diff --git a/src/main/resources/tech/minediamond/vortex/ui/searchPanel.fxml b/src/main/resources/tech/minediamond/vortex/ui/searchPanel.fxml new file mode 100644 index 0000000..b01525b --- /dev/null +++ b/src/main/resources/tech/minediamond/vortex/ui/searchPanel.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + diff --git a/src/test/java/tech/minediamond/vortex/service/EverythingServiceTest.java b/src/test/java/tech/minediamond/vortex/service/EverythingServiceTest.java index 1fa653b..da8eae1 100644 --- a/src/test/java/tech/minediamond/vortex/service/EverythingServiceTest.java +++ b/src/test/java/tech/minediamond/vortex/service/EverythingServiceTest.java @@ -23,10 +23,9 @@ import com.google.inject.Inject; import com.google.inject.Injector; import tech.minediamond.vortex.config.AppModule; -import tech.minediamond.vortex.model.search.EverythingResult; +import tech.minediamond.vortex.model.fileData.FileData; import tech.minediamond.vortex.model.search.SearchMode; import tech.minediamond.vortex.service.search.EverythingService; -import tech.minediamond.vortex.util.OpenResourceUtil; import java.io.IOException; import java.nio.file.Path; @@ -51,7 +50,7 @@ public static void main(String[] args) throws IOException, InterruptedException ArrayList folders = new ArrayList<>(); folders.add(Paths.get("D:\\myDounment")); folders.add(Paths.get("F:\\software_play_in_F")); - List results = everythingServiceTest.service.QueryBuilder() + List results = everythingServiceTest.service.QueryBuilder() .searchFor("askding") .inFolders(folders) .mode(SearchMode.ALL)