Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show dialog to select customizations #33

Merged
merged 11 commits into from
Sep 30, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ public static String get(final String key) {
return PREFERENCES.get(key, null);
}

public static void remove(final String key) {
PREFERENCES.remove(key);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ private void setupAuthStatusListeners() {
authStatusChangedListener = this::handleAuthStatusChange;
AuthUtils.addAuthStatusChangeListener(amazonQCommonActions.getSignoutAction());
AuthUtils.addAuthStatusChangeListener(amazonQCommonActions.getFeedbackDialogContributionAction());
AuthUtils.addAuthStatusChangeListener(amazonQCommonActions.getCustomizationDialogContributionAction());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.eclipse.amazonq.views;

import java.util.List;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import software.amazon.awssdk.utils.StringUtils;
import software.aws.toolkits.eclipse.amazonq.configuration.PluginStore;
import software.aws.toolkits.eclipse.amazonq.util.PluginLogger;
import software.aws.toolkits.eclipse.amazonq.views.model.Customization;

public final class CustomizationDialog extends Dialog {

private static final String TITLE = "Amazon Q Customization";
public static final String CUSTOMIZATION_STORAGE_INTERNAL_KEY = "aws.q.customization.eclipse";
private Composite container;
private Combo combo;
private Font magnifiedFont;
private Font boldFont;
private List<Customization> customizationsResponse;
private ResponseSelection responseSelection;
private String selectedCustomisationArn;

public enum ResponseSelection {
AMAZON_Q_FOUNDATION_DEFAULT,
CUSTOMIZATION
}

private final class CustomRadioButton extends Composite {
private Button radioButton;
private Label textLabel;
private Label subtextLabel;

CustomRadioButton(final Composite parent, final String text, final String subText, final int style) {
super(parent, style);
Composite contentComposite = new Composite(parent, SWT.FILL);
GridLayout gridLayout = new GridLayout(2, false);
contentComposite.setLayout(gridLayout);
contentComposite.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));

radioButton = new Button(contentComposite, SWT.RADIO);
radioButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));

textLabel = createLabelWithFontSize(contentComposite, text, 16);
textLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));

new Label(contentComposite, SWT.NONE);

subtextLabel = createLabelWithFontSize(contentComposite, subText, 16);
subtextLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
subtextLabel.setForeground(contentComposite.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
}

public Button getRadioButton() {
return radioButton;
}
}

public CustomizationDialog(final Shell parentShell) {
super(parentShell);
}

public void setCustomisationResponse(final List<Customization> customizationsResponse) {
this.customizationsResponse = customizationsResponse;
}

public List<Customization> getCustomizationResponse() {
return this.customizationsResponse;
}

public void setResponseSelection(final ResponseSelection responseSelection) {
this.responseSelection = responseSelection;
}

public ResponseSelection getResponseSelection() {
return this.responseSelection;
}

public void setSelectedCustomizationArn(final String arn) {
this.selectedCustomisationArn = arn;
}

public String getSelectedCustomizationArn() {
return this.selectedCustomisationArn;
}

@Override
protected void createButtonsForButtonBar(final Composite parent) {
createButton(parent, IDialogConstants.OK_ID, "Select", true);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
}

@Override
protected void okPressed() {
PluginLogger.info(String.format("Select pressed with responseSelection:%s and selectedArn:%s", this.responseSelection, this.selectedCustomisationArn));
if (this.responseSelection.equals(ResponseSelection.AMAZON_Q_FOUNDATION_DEFAULT)) {
PluginStore.remove(CUSTOMIZATION_STORAGE_INTERNAL_KEY);
} else {
// TODO: Add the logic to trigger notification to LSP server regarding change of configuration
PluginStore.put(CUSTOMIZATION_STORAGE_INTERNAL_KEY, this.selectedCustomisationArn);
}
super.okPressed();
}

private Font magnifyFontSize(final Font originalFont, final int fontSize) {
FontData[] fontData = originalFont.getFontData();
for (int i = 0; i < fontData.length; i++) {
fontData[i].setHeight(fontSize);
}
Font magnifiedFont = new Font(getShell().getDisplay(), fontData);
if (this.magnifiedFont != null && !this.magnifiedFont.isDisposed()) {
this.magnifiedFont.dispose();
}
this.magnifiedFont = magnifiedFont;
return magnifiedFont;
}

private Font boldFont(final Font originalFont) {
FontData[] fontData = originalFont.getFontData();
for (FontData data : fontData) {
data.setStyle(SWT.BOLD);
}
Font boldFont = new Font(getShell().getDisplay(), fontData);
if (this.boldFont != null && !this.boldFont.isDisposed()) {
this.boldFont.dispose();
}
this.boldFont = boldFont;
return boldFont;
}

private static void addFormattedOption(final Combo combo, final String name, final String description) {
String formattedText = name + " (" + description + ")";
combo.add(formattedText);
}

private void createDropdownForCustomizations(final Composite parent) {
Composite contentComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginLeft = 18;
contentComposite.setLayout(layout);
GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
layoutData.horizontalSpan = 2;
contentComposite.setLayoutData(layoutData);
combo = new Combo(contentComposite, SWT.READ_ONLY);
combo.setLayout(new GridLayout());
GridData comboGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
comboGridData.horizontalAlignment = GridData.FILL;
comboGridData.grabExcessHorizontalSpace = true;
comboGridData.horizontalSpan = 2;
combo.setLayoutData(comboGridData);
List<Customization> customizations = this.customizationsResponse;
int defaultSelectedDropdownIndex = -1;
for (int index = 0; index < customizations.size(); index++) {
addFormattedOption(combo, customizations.get(index).getName(), customizations.get(index).getDescription());
combo.setData(String.format("%s", index), customizations.get(index).getArn());
if (this.responseSelection.equals(ResponseSelection.CUSTOMIZATION)
&& StringUtils.isNotBlank(this.selectedCustomisationArn)
&& this.selectedCustomisationArn.equals(customizations.get(index).getArn())) {
defaultSelectedDropdownIndex = index;
}
}
combo.select(defaultSelectedDropdownIndex);
if (this.responseSelection.equals(ResponseSelection.AMAZON_Q_FOUNDATION_DEFAULT)) {
combo.setEnabled(false);
}
combo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
int selectedIndex = combo.getSelectionIndex();
String selectedOption = combo.getItem(selectedIndex);
String selectedCustomizationArn = (String) combo.getData(String.valueOf(selectedIndex));
CustomizationDialog.this.selectedCustomisationArn = selectedCustomizationArn;
PluginLogger.info(String.format("Selected option:%s with arn:%s", selectedOption, selectedCustomizationArn));
}
});
}

@Override
protected Control createDialogArea(final Composite parent) {
container = (Composite) super.createDialogArea(parent);
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginLeft = 10;
gridLayout.marginRight = 10;
gridLayout.marginTop = 10;
container.setLayout(gridLayout);
container.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
Label heading = createLabelWithFontSize(container, "Select an Amazon Q Customization", 18);
GridData layoutWithHorizontalSpan = new GridData();
layoutWithHorizontalSpan.horizontalSpan = 2;
heading.setLayoutData(layoutWithHorizontalSpan);
heading.setFont(boldFont(heading.getFont()));
Boolean isDefaultAmazonQFoundationSelected = this.responseSelection.equals(ResponseSelection.AMAZON_Q_FOUNDATION_DEFAULT);
CustomRadioButton defaultAmazonQFoundationButton = createCustomRadioButton(container, "Amazon Q foundation (Default)",
"Receive suggestions from Amazon Q base model.", SWT.NONE, isDefaultAmazonQFoundationSelected);
defaultAmazonQFoundationButton.setLayoutData(layoutWithHorizontalSpan);
CustomRadioButton customizationButton = createCustomRadioButton(container, "Customization",
"Receive Amazon Q suggestions based on your company's codebase.", SWT.NONE, !isDefaultAmazonQFoundationSelected);
customizationButton.setLayoutData(layoutWithHorizontalSpan);
defaultAmazonQFoundationButton.getRadioButton().addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
customizationButton.getRadioButton().setSelection(false);
responseSelection = ResponseSelection.AMAZON_Q_FOUNDATION_DEFAULT;
selectedCustomisationArn = null;
combo.setEnabled(false);
}
});
customizationButton.getRadioButton().addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
defaultAmazonQFoundationButton.getRadioButton().setSelection(false);
responseSelection = ResponseSelection.CUSTOMIZATION;
combo.setEnabled(true);
}
});
createDropdownForCustomizations(container);
createSeparator(container);
return container;
}

private Label createLabelWithFontSize(final Composite parent, final String text, final int fontSize) {
Label label = new Label(parent, SWT.NONE);
label.setText(text);
label.setFont(magnifyFontSize(label.getFont(), fontSize));
return label;
}

private void createSeparator(final Composite parent) {
Label separatorLabel = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData separatorLayout = new GridData(SWT.FILL, SWT.CENTER, true, false);
separatorLabel.setLayoutData(separatorLayout);
}

private CustomRadioButton createCustomRadioButton(final Composite parent, final String text,
final String subtext, final int style, final boolean isSelected) {
CustomRadioButton button = new CustomRadioButton(parent, text, subtext, style);
button.getRadioButton().setSelection(isSelected);
return button;
}

@Override
protected void configureShell(final Shell newShell) {
super.configureShell(newShell);
newShell.setText(TITLE);
}

@Override
protected Point getInitialSize() {
return new Point(600, 400);
}

@Override
public boolean close() {
disposeAllComponents(container);
disposeIndependentElements();
return super.close();
}

private void disposeAllComponents(final Composite container) {
for (Control control : container.getChildren()) {
if (control instanceof Composite) {
disposeAllComponents((Composite) control);
} else {
control.dispose();
}
}
}

public void disposeIndependentElements() {
if (this.magnifiedFont != null && !this.magnifiedFont.isDisposed()) {
this.magnifiedFont.dispose();
}
if (this.boldFont != null && !this.boldFont.isDisposed()) {
this.boldFont.dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public final class AmazonQCommonActions {
private ChangeThemeAction changeThemeAction;
private SignoutAction signoutAction;
private FeedbackDialogContributionItem feedbackDialogContributionItem;
private CustomizationDialogContributionItem customizationDialogContributionItem;

public AmazonQCommonActions(final Browser browser, final boolean isLoggedIn, final IViewSite viewSite) {
createActions(browser, isLoggedIn, viewSite);
Expand All @@ -32,10 +33,15 @@ public FeedbackDialogContributionItem getFeedbackDialogContributionAction() {
return feedbackDialogContributionItem;
}

public CustomizationDialogContributionItem getCustomizationDialogContributionAction() {
return customizationDialogContributionItem;
}

private void createActions(final Browser browser, final boolean isLoggedIn, final IViewSite viewSite) {
changeThemeAction = new ChangeThemeAction(browser);
signoutAction = new SignoutAction();
feedbackDialogContributionItem = new FeedbackDialogContributionItem(viewSite);
customizationDialogContributionItem = new CustomizationDialogContributionItem(viewSite);
}

private void contributeToActionBars(final IViewSite viewSite) {
Expand All @@ -46,6 +52,7 @@ private void contributeToActionBars(final IViewSite viewSite) {

private void fillLocalPullDown(final IMenuManager manager) {
manager.add(changeThemeAction);
manager.add(customizationDialogContributionItem);
manager.add(feedbackDialogContributionItem.getDialogContributionItem());
manager.add(signoutAction);
}
Expand All @@ -57,6 +64,7 @@ private void fillLocalToolBar(final IToolBarManager manager) {
public void updateActionVisibility(final boolean isLoggedIn, final IViewSite viewSite) {
signoutAction.updateVisibility(isLoggedIn);
feedbackDialogContributionItem.updateVisibility(isLoggedIn);
customizationDialogContributionItem.updateVisibility(isLoggedIn);
}

}
Loading