Skip to content

Commit

Permalink
Merge branch 'jdk8'
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorndarri committed Nov 6, 2023
2 parents 0c8742a + 668fbf6 commit 7c22cd9
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 13 deletions.
6 changes: 5 additions & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9886,4 +9886,8 @@
EntitySearchField.setSelectionProvider() replaced with setSelectionProviderFactory(), selectionProvider now dynamically created instead of having it hang around in memory, SelectionProvider.updateUI() removed
EntitySearchField.SelectionProvider.selectEntities() renamed select()
EntitySearchModel.SelectionProvider renamed Selector
SelectionProvider renamed Selector and moved to SelectionDialogBuilder, select() parameter now JComponent dialogOwner
SelectionProvider renamed Selector and moved to SelectionDialogBuilder, select() parameter now JComponent dialogOwner
EntitySearchModel.limit() added, along with builder method and configuration value
EntitySearchField now displays a message in case the search result limit has been reached
EntitySearchField.Builder.limit() convenience method added
EntitySearchField, limit added to settings panel
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ final class DefaultEntitySearchModel implements EntitySearchModel {
private final Value<Character> wildcard = Value.value(Text.WILDCARD_CHARACTER.get(), Text.WILDCARD_CHARACTER.get());
private final Value<Supplier<Condition>> condition = Value.value(NULL_CONDITION, NULL_CONDITION);
private final Value<Function<Entity, String>> stringFunction = Value.value(DEFAULT_TO_STRING, DEFAULT_TO_STRING);
private final Value<Integer> limit;
private final State selectionEmpty = State.state(true);
private final String description;

Expand All @@ -81,6 +82,7 @@ private DefaultEntitySearchModel(DefaultBuilder builder) {
this.description = builder.description == null ? createDescription() : builder.description;
this.singleSelection = builder.singleSelection;
this.selectedEntities.addValidator(new EntityValidator());
this.limit = Value.value(builder.limit, builder.limit);
bindEventsInternal();
}

Expand Down Expand Up @@ -124,6 +126,11 @@ public Value<Character> wildcard() {
return wildcard;
}

@Override
public Value<Integer> limit() {
return limit;
}

@Override
public Value<Supplier<Condition>> condition() {
return condition;
Expand Down Expand Up @@ -200,13 +207,17 @@ private Select select() {
}
}
}

return Select.where(createCombinedCondition(conditions))
.limit(limit.get())
.build();
}

private Condition createCombinedCondition(Collection<Condition> conditions) {
Condition conditionCombination = or(conditions);
Condition additionalCondition = condition.get().get();
Select.Builder selectBuilder = additionalCondition == null ?
Select.where(conditionCombination) :
Select.where(and(additionalCondition, conditionCombination));

return selectBuilder.build();
return additionalCondition == null ? conditionCombination : and(additionalCondition, conditionCombination);
}

private String prepareSearchString(String rawSearchString, SearchSettings searchSettings) {
Expand Down Expand Up @@ -299,6 +310,7 @@ static final class DefaultBuilder implements Builder {
private String description;
private boolean singleSelection = false;
private String separator = DEFAULT_SEPARATOR;
private int limit = LIMIT.get();

DefaultBuilder(EntityType entityType, EntityConnectionProvider connectionProvider) {
this.entityType = requireNonNull(entityType);
Expand Down Expand Up @@ -340,6 +352,12 @@ public Builder separator(String separator) {
return this;
}

@Override
public Builder limit(int limit) {
this.limit = limit;
return this;
}

@Override
public EntitySearchModel build() {
return new DefaultEntitySearchModel(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package is.codion.framework.model;

import is.codion.common.Configuration;
import is.codion.common.property.PropertyValue;
import is.codion.common.state.State;
import is.codion.common.state.StateObserver;
import is.codion.common.value.Value;
Expand All @@ -40,6 +42,13 @@
*/
public interface EntitySearchModel {

/**
* Specifies the default search result limit, that is, the maximum number of results, -1 meaning no limit<br>
* Value type: Integer<br>
* Default value: -1
*/
PropertyValue<Integer> LIMIT = Configuration.integerValue("is.codion.framework.model.EntitySearchModel.limit", -1);

/**
* @return the type of the entity this search model is based on
*/
Expand Down Expand Up @@ -80,6 +89,11 @@ public interface EntitySearchModel {
*/
Value<Character> wildcard();

/**
* @return the value controlling the search result limit
*/
Value<Integer> limit();

/**
* Performs a query based on the current search configuration
* @return a list containing the entities fulfilling the current condition
Expand Down Expand Up @@ -193,6 +207,12 @@ interface Builder {
*/
Builder separator(String multipleItemSeparator);

/**
* @param limit the search result limit
* @return this builder
*/
Builder limit(int limit);

/**
* @return a new {@link EntitySearchModel} based on this builder
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@
* {@link is.codion.framework.model.ForeignKeyDetailModelLink#SEARCH_BY_INSERTED_ENTITY}<br>
* {@link is.codion.framework.model.ForeignKeyDetailModelLink#REFRESH_ON_SELECTION}<br>
* {@link is.codion.framework.model.ForeignKeyDetailModelLink#CLEAR_FOREIGN_KEY_ON_EMPTY_SELECTION}<br>
* {@link is.codion.framework.model.EntitySearchModel#LIMIT}<br>
*/
package is.codion.framework.model;
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ void condition() {
assertTrue(result.isEmpty());
}

@Test
void limit() {
searchModel.searchString().set("j");
assertEquals(4, searchModel.search().size());
searchModel.limit().set(3);
assertEquals(3, searchModel.search().size());
searchModel.limit().set(null);
assertEquals(4, searchModel.search().size());
}

@BeforeEach
void setUp() throws Exception {
searchColumns = asList(Employee.NAME, Employee.JOB);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SortOrder;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import java.awt.BorderLayout;
import java.awt.CardLayout;
Expand All @@ -97,12 +98,14 @@
import static is.codion.swing.common.ui.Colors.darker;
import static is.codion.swing.common.ui.Utilities.linkToEnabledState;
import static is.codion.swing.common.ui.border.Borders.emptyBorder;
import static is.codion.swing.common.ui.component.Components.gridLayoutPanel;
import static is.codion.swing.common.ui.component.Components.menu;
import static is.codion.swing.common.ui.component.text.TextComponents.selectAllOnFocusGained;
import static is.codion.swing.common.ui.layout.Layouts.borderLayout;
import static java.awt.event.InputEvent.CTRL_DOWN_MASK;
import static java.awt.event.InputEvent.SHIFT_DOWN_MASK;
import static java.awt.event.KeyEvent.*;
import static java.text.MessageFormat.format;
import static java.util.Collections.emptyList;
import static java.util.Objects.requireNonNull;

Expand Down Expand Up @@ -326,6 +329,12 @@ public interface Builder extends ComponentBuilder<Entity, EntitySearchField, Bui
* @return this builder instance
*/
Builder selectorFactory(Function<EntitySearchModel, Selector> selectorFactory);

/**
* @param limit the search result limit
* @return this builder instance
*/
Builder limit(int limit);
}

private void bindEvents() {
Expand Down Expand Up @@ -483,9 +492,7 @@ private void initializeUI(EntitySearchModel searchModel) {
setLayout(borderLayout());
setBorder(emptyBorder());
add(createSearchColumnPanel(searchModel), BorderLayout.CENTER);
if (!searchModel.singleSelection()) {
add(createSeparatorPanel(searchModel), BorderLayout.SOUTH);
}
add(createSouthPanel(searchModel), BorderLayout.SOUTH);
}

private static JPanel createSearchColumnPanel(EntitySearchModel searchModel) {
Expand All @@ -510,17 +517,39 @@ private static JPanel createSearchColumnPanel(EntitySearchModel searchModel) {
.build();
}

private static JPanel createSouthPanel(EntitySearchModel searchModel) {
PanelBuilder southPanelBuilder = gridLayoutPanel(1, 0)
.border(BorderFactory.createTitledBorder(""));
if (!searchModel.singleSelection()) {
southPanelBuilder.add(createSeparatorPanel(searchModel));
}
else {
southPanelBuilder.add(new JLabel());
}
southPanelBuilder.add(createLimitPanel(searchModel));

return southPanelBuilder.build();
}

private static JPanel createSeparatorPanel(EntitySearchModel searchModel) {
return Components.borderLayoutPanel()
.border(BorderFactory.createTitledBorder(""))
.centerComponent(new JLabel(MESSAGES.getString("multiple_item_separator")))
.westComponent(Components.textField(searchModel.separator())
.westComponent(new JLabel(MESSAGES.getString("multiple_item_separator")))
.centerComponent(Components.textField(searchModel.separator())
.columns(1)
.maximumLength(1)
.build())
.build();
}

private static JPanel createLimitPanel(EntitySearchModel searchModel) {
return Components.borderLayoutPanel()
.westComponent(new JLabel(MESSAGES.getString("result_limit")))
.centerComponent(Components.integerField(searchModel.limit())
.columns(4)
.build())
.build();
}

private static JPanel createColumnSettingsPanel(EntitySearchModel.SearchSettings settings) {
return Components.gridLayoutPanel(3, 1)
.add(Components.checkBox(settings.caseSensitive())
Expand Down Expand Up @@ -597,14 +626,19 @@ public static TableSelector tableSelector(EntitySearchModel searchModel) {

private static final class DefaultListSelector implements ListSelector {

private final EntitySearchModel searchModel;
private final DefaultListModel<Entity> listModel = new DefaultListModel<>();
private final JList<Entity> list = new JList<>(listModel);
private final JScrollPane scrollPane = new JScrollPane(list);
private final JPanel basePanel = new JPanel(borderLayout());
private final JLabel resultLimitLabel = Components.label()
.horizontalAlignment(SwingConstants.RIGHT)
.build();
private final Control selectControl;

private DefaultListSelector(EntitySearchModel searchModel) {
selectControl = Control.builder(new SelectCommand(requireNonNull(searchModel), list))
this.searchModel = requireNonNull(searchModel);
selectControl = Control.builder(new SelectCommand(searchModel, list))
.name(Messages.ok())
.build();
list.setSelectionMode(searchModel.singleSelection() ?
Expand All @@ -620,6 +654,9 @@ public void mouseClicked(MouseEvent e) {
}
});
basePanel.add(scrollPane, BorderLayout.CENTER);
basePanel.add(resultLimitLabel, BorderLayout.SOUTH);
int gap = Layouts.HORIZONTAL_VERTICAL_GAP.get();
basePanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, 0, gap));
}

@Override
Expand All @@ -631,6 +668,7 @@ public JList<Entity> list() {
public void select(JComponent dialogOwner, List<Entity> entities) {
requireNonNull(entities).forEach(listModel::addElement);
list.scrollRectToVisible(list.getCellBounds(0, 0));
initializeResultLimitMessage(resultLimitLabel, searchModel.limit().get(), entities.size());

Dialogs.okCancelDialog(basePanel)
.owner(dialogOwner)
Expand Down Expand Up @@ -666,14 +704,18 @@ public void perform() {

private static final class DefaultTableSelector implements TableSelector {

private final EntitySearchModel searchModel;
private final FilteredTable<Entity, Attribute<?>> table;
private final JScrollPane scrollPane;
private final JPanel searchPanel = new JPanel(borderLayout());
private final JPanel basePanel = new JPanel(borderLayout());
private final JLabel resultLimitLabel = Components.label()
.horizontalAlignment(SwingConstants.RIGHT)
.build();
private final Control selectControl;

private DefaultTableSelector(EntitySearchModel searchModel) {
requireNonNull(searchModel);
this.searchModel = requireNonNull(searchModel);
SwingEntityTableModel tableModel = new SwingEntityTableModel(searchModel.entityType(), searchModel.connectionProvider()) {
@Override
protected Collection<Entity> refreshItems() {
Expand Down Expand Up @@ -706,6 +748,7 @@ protected Collection<Entity> refreshItems() {
tableModel.sortModel().setSortOrder(searchColumns.iterator().next(), SortOrder.ASCENDING);
scrollPane = new JScrollPane(table);
searchPanel.add(table.searchField(), BorderLayout.WEST);
searchPanel.add(resultLimitLabel, BorderLayout.CENTER);
basePanel.add(scrollPane, BorderLayout.CENTER);
basePanel.add(searchPanel, BorderLayout.SOUTH);
int gap = Layouts.HORIZONTAL_VERTICAL_GAP.get();
Expand All @@ -723,6 +766,7 @@ public FilteredTable<Entity, Attribute<?>> table() {
public void select(JComponent dialogOwner, List<Entity> entities) {
table.getModel().addItemsAtSorted(0, requireNonNull(entities));
table.scrollRectToVisible(table.getCellRect(0, 0, true));
initializeResultLimitMessage(resultLimitLabel, searchModel.limit().get(), entities.size());

Dialogs.okCancelDialog(basePanel)
.owner(dialogOwner)
Expand Down Expand Up @@ -751,6 +795,15 @@ private void configureColumn(FilteredTableColumn<Attribute<?>> column) {
}
}

private static void initializeResultLimitMessage(JLabel label, int limit, int resultSize) {
boolean resultLimitReached = limit == resultSize;
if (resultLimitReached) {
label.setText(format(MESSAGES.getString("result_limited"), limit));
label.setVisible(true);
}
label.setVisible(resultLimitReached);
}

private static final class SingleSelectionValue extends AbstractComponentValue<Entity, EntitySearchField> {

private SingleSelectionValue(EntitySearchField searchField) {
Expand Down Expand Up @@ -936,6 +989,12 @@ public Builder selectorFactory(Function<EntitySearchModel, Selector> selectorFac
return this;
}

@Override
public Builder limit(int limit) {
this.searchModel.limit().set(limit);
return this;
}

@Override
protected EntitySearchField createComponent() {
return new EntitySearchField(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ postfix_wildcard=Auto-postfix wildcard
prefix_wildcard=Auto-prefix wildcard
select_entity=Select record
searching=Searching
result_limited=Result limited to {0, choice, 1#record|1<{0, number, integer} records}
result_limit=Result limit
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ postfix_wildcard=Sj\u00E1lfkrafa algildi fyrir aftan
prefix_wildcard=Sj\u00E1lfkrafa algildi fyrir framan
select_entity=Veldu f\u00E6rslu
searching=Leita
result_limited=Ni\u00F0urst\u00F6\u00F0ur takmarka\u00F0ar vi\u00F0 {0, choice, 1#f\u00E6rslu|1<{0, number, integer} f\u00E6rslur}
result_limit=Fj\u00F6ldatakm\u00F6rkun

0 comments on commit 7c22cd9

Please sign in to comment.