From 0cc160a02c7b45b1d8b5011ea7325bb07d138310 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Thu, 9 Apr 2026 10:22:51 -0600 Subject: [PATCH] Unify Table Behavior --- .../controllers/AdoptionController.java | 2 ++ .../controllers/AppointmentController.java | 4 ++- .../controllers/InventoryController.java | 2 ++ .../controllers/PetController.java | 2 ++ .../controllers/ProductController.java | 2 ++ .../ProductSupplierController.java | 2 ++ .../controllers/PurchaseOrderController.java | 4 +-- .../controllers/SaleController.java | 14 ++------ .../controllers/ServiceController.java | 2 ++ .../controllers/StaffAccountsController.java | 8 ++++- .../controllers/SupplierController.java | 2 ++ .../petshopdesktop/util/TableViewSupport.java | 33 +++++++++++++++++++ 12 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 desktop/src/main/java/org/example/petshopdesktop/util/TableViewSupport.java diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java index 7b5b6a5f..d31785be 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java @@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.endpoints.AdoptionApi; import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController; import org.example.petshopdesktop.models.Adoption; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.io.IOException; import java.util.Comparator; @@ -80,6 +81,7 @@ public class AdoptionController { colAdoptionStatus.setCellValueFactory(new PropertyValueFactory<>("adoptionStatus")); displayAdoptions(); + TableViewSupport.installDoubleClickAction(tvAdoptions, selected -> openDialog(selected, "Edit")); tvAdoptions.getSelectionModel().selectedItemProperty().addListener( (observable, oldValue, newValue) -> { diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java index e6eb87b5..3b19567c 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java @@ -18,6 +18,7 @@ import org.example.petshopdesktop.api.dto.appointment.AppointmentResponse; import org.example.petshopdesktop.api.endpoints.AppointmentApi; import org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.util.List; import java.util.Comparator; @@ -61,7 +62,8 @@ public class AppointmentController { colAppointmentStatus.setCellValueFactory(new PropertyValueFactory<>("appointmentStatus")); filtered = new FilteredList<>(appointments, a -> true); - tvAppointments.setItems(filtered); + TableViewSupport.bindSortedItems(tvAppointments, filtered); + TableViewSupport.installDoubleClickAction(tvAppointments, selected -> openDialog(selected, "Edit")); if (txtSearch != null) { txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n)); diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java index 1153fe04..d889237d 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java @@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.endpoints.InventoryApi; import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController; import org.example.petshopdesktop.models.Inventory; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.io.IOException; import java.util.List; @@ -70,6 +71,7 @@ public class InventoryController { colQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity")); displayInventory(); + TableViewSupport.installDoubleClickAction(tvInventory, selected -> openDialog(selected, "Edit")); tvInventory.getSelectionModel().selectedItemProperty().addListener( (observable, oldValue, newValue) -> { diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/PetController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/PetController.java index 3e9052e4..fbe2df24 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/PetController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/PetController.java @@ -22,6 +22,7 @@ import org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogControl import org.example.petshopdesktop.models.Pet; import org.example.petshopdesktop.util.ActivityLogger; import org.example.petshopdesktop.util.DesktopImageSupport; +import org.example.petshopdesktop.util.TableViewSupport; import java.io.IOException; import java.util.List; @@ -172,6 +173,7 @@ public class PetController { cbStatusFilter.getSelectionModel().selectFirst(); displayPets(); + TableViewSupport.installDoubleClickAction(tvPets, selected -> openDialog(selected, "Edit")); tvPets.getSelectionModel().selectedItemProperty().addListener( (observable, oldValue, newValue) -> { diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductController.java index 61702f3b..c27974b2 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductController.java @@ -22,6 +22,7 @@ import org.example.petshopdesktop.api.endpoints.ProductApi; import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController; import org.example.petshopdesktop.util.ActivityLogger; import org.example.petshopdesktop.util.DesktopImageSupport; +import org.example.petshopdesktop.util.TableViewSupport; import java.io.IOException; import java.util.ArrayList; @@ -95,6 +96,7 @@ public class ProductController { loadCategoryFilter(); displayProduct(); + TableViewSupport.installDoubleClickAction(tvProducts, selected -> openDialog(selected, "Edit")); //EventListener to Enable buttons when a row is selected tvProducts.getSelectionModel().selectedItemProperty().addListener( diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java index 1e9b9a95..4a632a1a 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java @@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierRespons import org.example.petshopdesktop.api.endpoints.ProductSupplierApi; import org.example.petshopdesktop.controllers.dialogcontrollers.ProductSupplierDialogController; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.io.IOException; import java.util.List; @@ -76,6 +77,7 @@ public class ProductSupplierController { colCost.setCellValueFactory(new PropertyValueFactory("cost")); displayProductSupplier(); + TableViewSupport.installDoubleClickAction(tvProductSuppliers, selected -> openDialog(selected, "Edit")); //EventListener to Enable buttons when a row is selected tvProductSuppliers.getSelectionModel().selectedItemProperty().addListener( diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java index d8ea54b6..de8334ab 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java @@ -11,6 +11,7 @@ import org.example.petshopdesktop.DTOs.PurchaseOrderDTO; import org.example.petshopdesktop.api.dto.purchaseorder.PurchaseOrderResponse; import org.example.petshopdesktop.api.endpoints.PurchaseOrderApi; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.util.List; import java.util.Comparator; @@ -49,7 +50,7 @@ public class PurchaseOrderController { new PropertyValueFactory<>("status")); filtered = new FilteredList<>(purchaseOrders, p -> true); - tvPurchaseOrders.setItems(filtered); + TableViewSupport.bindSortedItems(tvPurchaseOrders, filtered); if (txtSearch != null) { txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n)); @@ -69,7 +70,6 @@ public class PurchaseOrderController { Platform.runLater(() -> { purchaseOrders.setAll(dtos); - tvPurchaseOrders.setItems(filtered); }); } catch (Exception e) { Platform.runLater(() -> { diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/SaleController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/SaleController.java index 22c96dbd..e0436bf5 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/SaleController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/SaleController.java @@ -7,7 +7,6 @@ import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.application.Platform; -import javafx.scene.input.MouseButton; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; @@ -37,6 +36,7 @@ import org.example.petshopdesktop.models.SaleCartItem; import org.example.petshopdesktop.models.SaleDetail; import org.example.petshopdesktop.models.SaleLineItem; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.math.BigDecimal; import java.text.NumberFormat; @@ -168,16 +168,8 @@ public class SaleController { colSalePaymentType.setCellValueFactory(new PropertyValueFactory<>("paymentMethod")); filteredSales = new FilteredList<>(saleItems, s -> true); - tvSales.setItems(filteredSales); - - tvSales.setOnMouseClicked(event -> { - if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) { - SaleLineItem selected = tvSales.getSelectionModel().getSelectedItem(); - if (selected != null) { - openSaleDetailDialog(selected.getSaleId()); - } - } - }); + TableViewSupport.bindSortedItems(tvSales, filteredSales); + TableViewSupport.installDoubleClickAction(tvSales, selected -> openSaleDetailDialog(selected.getSaleId())); txtSearch.textProperty().addListener((obs, oldVal, newVal) -> applySalesFilter(newVal)); } diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java index 8500677a..dce27137 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java @@ -15,6 +15,7 @@ import org.example.petshopdesktop.api.dto.service.ServiceResponse; import org.example.petshopdesktop.api.endpoints.ServiceApi; import org.example.petshopdesktop.controllers.dialogcontrollers.ServiceDialogController; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import javafx.stage.Modality; import java.util.List; @@ -54,6 +55,7 @@ public class ServiceController { colServicePrice.setCellValueFactory(new PropertyValueFactory<>("servicePrice")); displayServices(); + TableViewSupport.installDoubleClickAction(tvServices, selected -> openDialog(selected, "Edit")); tvServices.getSelectionModel().selectedItemProperty().addListener( (observable, oldValue, newValue) -> { diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java index bec351a4..fbd3bd87 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java @@ -21,6 +21,7 @@ import org.example.petshopdesktop.api.endpoints.EmployeeApi; import org.example.petshopdesktop.auth.UserSession; import org.example.petshopdesktop.models.StaffAccount; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.sql.Timestamp; import java.time.ZoneId; @@ -76,7 +77,8 @@ public class StaffAccountsController { colCreated.setCellValueFactory(new PropertyValueFactory<>("createdAt")); filtered = new FilteredList<>(staffAccounts, a -> true); - tvStaff.setItems(filtered); + TableViewSupport.bindSortedItems(tvStaff, filtered); + TableViewSupport.installDoubleClickAction(tvStaff, this::openEditDialog); txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n)); @@ -131,6 +133,10 @@ public class StaffAccountsController { void btnEditAccountClicked(ActionEvent event) { lblError.setText(""); StaffAccount selected = tvStaff.getSelectionModel().getSelectedItem(); + openEditDialog(selected); + } + + private void openEditDialog(StaffAccount selected) { if (selected == null) { lblError.setText("Select a staff account to edit."); return; diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java index 28248657..b31070d3 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java @@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.endpoints.SupplierApi; import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController; import org.example.petshopdesktop.models.Supplier; import org.example.petshopdesktop.util.ActivityLogger; +import org.example.petshopdesktop.util.TableViewSupport; import java.io.IOException; import java.util.List; @@ -78,6 +79,7 @@ public class SupplierController { colSupplierPhone.setCellValueFactory(new PropertyValueFactory("supPhone")); displaySupplier(); + TableViewSupport.installDoubleClickAction(tvSuppliers, selected -> openDialog(selected, "Edit")); //EventListener to Enable buttons when a row is selected tvSuppliers.getSelectionModel().selectedItemProperty().addListener( diff --git a/desktop/src/main/java/org/example/petshopdesktop/util/TableViewSupport.java b/desktop/src/main/java/org/example/petshopdesktop/util/TableViewSupport.java new file mode 100644 index 00000000..9d5d327c --- /dev/null +++ b/desktop/src/main/java/org/example/petshopdesktop/util/TableViewSupport.java @@ -0,0 +1,33 @@ +package org.example.petshopdesktop.util; + +import javafx.collections.transformation.FilteredList; +import javafx.collections.transformation.SortedList; +import javafx.scene.control.TableRow; +import javafx.scene.control.TableView; +import javafx.scene.input.MouseButton; + +import java.util.function.Consumer; + +public final class TableViewSupport { + + private TableViewSupport() { + } + + public static void bindSortedItems(TableView tableView, FilteredList filteredItems) { + SortedList sortedItems = new SortedList<>(filteredItems); + sortedItems.comparatorProperty().bind(tableView.comparatorProperty()); + tableView.setItems(sortedItems); + } + + public static void installDoubleClickAction(TableView tableView, Consumer action) { + tableView.setRowFactory(tv -> { + TableRow row = new TableRow<>(); + row.setOnMouseClicked(event -> { + if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2 && !row.isEmpty()) { + action.accept(row.getItem()); + } + }); + return row; + }); + } +}