Package org.rhq.coregui.client.util.enhanced

Examples of org.rhq.coregui.client.util.enhanced.EnhancedVLayout


    public SystemSettingsView() {
        super();
        setHeight100();
        setWidth100();

        canvas = new EnhancedVLayout();
        canvas.setHeight100();
        canvas.setWidth100();
        canvas.setMargin(15);
        addMember(canvas);
    }
View Full Code Here


    public Canvas getCanvas() {
        boolean newCanvas = this.vLayout == null;

        if (newCanvas) {
            this.vLayout = new EnhancedVLayout();

            // only create the timeout member 1 time, even if we end up recreating the config editor
            TreeSet<TimeUnit> supportedUnits = new TreeSet<TimeUnit>();
            supportedUnits.add(TimeUnit.SECONDS);
            supportedUnits.add(TimeUnit.MINUTES);
View Full Code Here

        tagEditor.setExtraSpace(10);
        return tagEditor;
    }

    private Canvas getActionLayout() {
        EnhancedVLayout actionLayout = new EnhancedVLayout(10);
        IButton deployButton = new EnhancedIButton(MSG.view_bundle_deploy(), ButtonColor.BLUE);
        //deployButton.setIcon(IconEnum.BUNDLE_DEPLOY.getIcon16x16Path());
        deployButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                new BundleDeployWizard(destination).startWizard();
            }
        });
        actionLayout.addMember(deployButton);

        IButton revertButton = new EnhancedIButton(MSG.view_bundle_revert(), ButtonColor.RED);
        //revertButton.setIcon(IconEnum.BUNDLE_REVERT.getIcon16x16Path());
        revertButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                SC.ask(MSG.view_bundle_dest_revertConfirm(), new BooleanCallback() {
                    @Override
                    public void execute(Boolean aBoolean) {
                        if (aBoolean) {
                            new BundleRevertWizard(destination).startWizard();
                        }
                    }
                });
            }
        });
        actionLayout.addMember(revertButton);

        IButton purgeButton = new EnhancedIButton(MSG.view_bundle_purge(), ButtonColor.RED);
        //purgeButton.setIcon(IconEnum.BUNDLE_DESTINATION_PURGE.getIcon16x16Path());
        purgeButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                SC.ask(MSG.view_bundle_dest_purgeConfirm(), new BooleanCallback() {
                    @Override
                    public void execute(Boolean aBoolean) {
                        if (aBoolean) {
                            BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService(600000); // 10m should be enough right?
                            bundleService.purgeBundleDestination(destination.getId(), new AsyncCallback<Void>() {
                                @Override
                                public void onFailure(Throwable caught) {
                                    getErrorHandler().handleError(
                                        MSG.view_bundle_dest_purgeFailure(destination.getName()), caught);
                                }

                                @Override
                                public void onSuccess(Void result) {
                                    getMessageCenter().notify(
                                        new Message(MSG.view_bundle_dest_purgeSuccessful(destination.getName()),
                                            Message.Severity.Info));
                                    // Bundle destination is purged, go back to bundle destination view
                                    goToView(LinkManager.getBundleDestinationLink(bundle.getId(), destination.getId()),
                                        true);
                                }
                            });
                        }
                    }
                });
            }
        });
        checkIfDisabled(purgeButton);
        actionLayout.addMember(purgeButton);

        IButton deleteButton = new EnhancedIButton(MSG.common_button_delete(), ButtonColor.RED);
        //deleteButton.setIcon(IconEnum.BUNDLE_DESTINATION_DELETE.getIcon16x16Path());
        deleteButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                SC.ask(MSG.view_bundle_dest_deleteConfirm(), new BooleanCallback() {
                    @Override
                    public void execute(Boolean confirmed) {
                        if (confirmed) {
                            doDeleteBundleDestination();
                        }
                    }
                });
            }
        });
        actionLayout.addMember(deleteButton);

        if (!canDelete) {
            deleteButton.setDisabled(true);
        }
View Full Code Here

        return MSG.view_bundle_deployWizard_getDestStep();
    }

    public Canvas getCanvas() {
        if (this.form == null) {
            this.form = new EnhancedVLayout();
            this.valForm.setWidth100();
            this.valForm.setNumCols(2);
            this.valForm.setColWidths("50%", "*");

            final TextItem nameTextItem = new TextItem("name", MSG.view_bundle_deployWizard_getDest_name());
View Full Code Here

        }

        if (configurationDefinition.getConfigurationFormat() == ConfigurationFormat.STRUCTURED
            || configurationDefinition.getConfigurationFormat() == ConfigurationFormat.STRUCTURED_AND_RAW) {
            Log.debug("Building structured configuration editor...");
            EnhancedVLayout structuredConfigLayout = buildStructuredPane();
            addMember(structuredConfigLayout);
        } else {
            Label label = new Label("Structured configuration is not supported.");
            addMember(label);
        }
View Full Code Here

        this.originalConfiguration = null; // so reload gets another copy
        reload();
    }

    protected EnhancedVLayout buildStructuredPane() {
        EnhancedVLayout layout = new EnhancedVLayout();
        List<PropertyGroupDefinition> groupDefinitions = configurationDefinition.getGroupDefinitions();

        if (groupDefinitions.isEmpty() || groupDefinitions.size() == 1) {
            // No or one prop groups, so we just need a single form for the non-grouped props
            // and another one if there is just one group
            List<PropertyDefinition> propertyDefinitions = new ArrayList<PropertyDefinition>(
                configurationDefinition.getNonGroupedProperties());
            if (!propertyDefinitions.isEmpty()) {
                DynamicForm form = buildPropertiesForm(propertyDefinitions, configuration);
                form.validate();
                layout.addMember(form);
            }
            if (groupDefinitions.size() == 1) {
                propertyDefinitions = new ArrayList<PropertyDefinition>(
                    configurationDefinition.getPropertiesInGroup(groupDefinitions.get(0).getName()));
                DynamicForm groupForm = buildPropertiesForm(propertyDefinitions, configuration);
                groupForm.setIsGroup(true);
                groupForm.setGroupTitle(groupDefinitions.get(0).getDisplayName());
                groupForm.validate();
                layout.addMember(groupForm);
            }
        } else {
            // Two or more prop groups, so create a section stack with one section per group.
            final SectionStack sectionStack = new SectionStack();
            sectionStack.setVisibilityMode(VisibilityMode.MULTIPLE);
            sectionStack.setWidth100();
            sectionStack.setHeight100();
            sectionStack.setScrollSectionIntoView(true);
            sectionStack.setOverflow(Overflow.AUTO);

            if (!configurationDefinition.getNonGroupedProperties().isEmpty()) {
                sectionStack.addSection(buildGroupSection(null));
            }

            for (PropertyGroupDefinition definition : groupDefinitions) {
                //            com.allen_sauer.gwt.log.client.Log.info("building: " + definition.getDisplayName());
                sectionStack.addSection(buildGroupSection(definition));
            }

            this.toolStrip = buildToolStrip(layout, sectionStack);
            layout.addMember(toolStrip);
            layout.addMember(sectionStack);
        }

        fireInitialPropertyChangedEvent();

        return layout;
View Full Code Here

            propertyDefinitionMapClone.setConfigurationDefinition(propertyDefinitionMap.getConfigurationDefinition());
            propertyDefinitionMapClone.setReadOnly(propertyDefinitionMap.isReadOnly());
            addMemberPropertyDefinitionsToDynamicPropertyMap(propertyDefinitionMapClone, propertyMap);
            propertyDefinitionMap = propertyDefinitionMapClone;
        }
        EnhancedVLayout layout = new EnhancedVLayout();

        HTMLFlow description = new HTMLFlow(propertyDefinitionMap.getDescription());
        layout.addMember(description);

        final PropertyDefinitionMap propertyDefinitionMapFinal = propertyDefinitionMap;
        DynamicForm valuesCanvas = buildPropertiesForm(propertyDefinitionMapFinal.getOrderedPropertyDefinitions(),
            propertyMap);
        layout.addMember(valuesCanvas);

        if (isDynamic && !isReadOnly(propertyDefinitionMap, propertyMap)) {
            // Map is not read-only - add footer with New and Delete buttons to allow user to add or remove members.
            EnhancedToolStrip buttonBar = new EnhancedToolStrip();
            buttonBar.setPadding(5);
            buttonBar.setMembersMargin(15);

            final IButton newButton = new EnhancedIButton(MSG.common_button_new(), ButtonColor.BLUE);
            newButton.setIcon(Window.getImgURL("[SKIN]/actions/add.png"));
            newButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    SC.askforValue(MSG.view_configEdit_enterPropName(), new ValueCallback() {
                        public void execute(String propertyName) {
                            if (propertyMap.get(propertyName) != null) {
                                CoreGUI.getMessageCenter().notify(
                                    new Message(MSG.view_configEdit_error_3(propertyName), Message.Severity.Error,
                                        EnumSet.of(Message.Option.Transient)));
                            } else {
                                PropertySimple memberPropertySimple = new PropertySimple(propertyName, null);
                                addPropertyToDynamicMap(memberPropertySimple, propertyMap);
                                firePropertyChangedEvent(propertyMap, propertyDefinitionMapFinal, true);

                                reload();

                                CoreGUI.getMessageCenter().notify(
                                    new Message(MSG.view_configEdit_msg_1(propertyName), EnumSet
                                        .of(Message.Option.Transient)));
                            }
                        }
                    });
                }
            });
            buttonBar.addMember(newButton);

            HLayout spacer = new HLayout();
            spacer.setWidth(12);
            buttonBar.addMember(spacer);

            EnhancedHLayout deleteControlsLayout = new EnhancedHLayout();
            deleteControlsLayout.setMargin(3);
            deleteControlsLayout.setMembersMargin(3);
            deleteControlsLayout.setWidth100();
            DynamicForm deleteForm = new DynamicForm();
            deleteForm.setWidth100();

            final SelectItem selectItem = new SortedSelectItem();
            selectItem.setMultiple(true);
            selectItem.setMultipleAppearance(MultipleAppearance.GRID);
            selectItem.setTitle(MSG.common_button_delete());
            selectItem.setValueMap(propertyDefinitionMap.getMap().keySet()
                .toArray(new String[propertyDefinitionMap.getMap().size()]));

            final EnhancedIButton okButton = new EnhancedIButton(MSG.common_button_ok(), ButtonColor.BLUE);
            okButton.setDisabled(true);
            okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    SC.confirm(MSG.view_configEdit_confirm_1(), new BooleanCallback() {
                        @Override
                        public void execute(Boolean confirmed) {
                            if (confirmed) {
                                Object value = selectItem.getValue();
                                if (value != null) {
                                    String stringValue = value.toString();
                                    String[] memberPropertyNames = stringValue.split(",");
                                    for (final String memberPropertyName : memberPropertyNames) {
                                        PropertySimple memberPropertySimple = propertyMap.getSimple(memberPropertyName);
                                        removePropertyFromDynamicMap(memberPropertySimple);
                                        firePropertyChangedEvent(propertyMap, propertyDefinitionMapFinal, true);
                                    }
                                }

                                reload();
                                CoreGUI.getMessageCenter().notify(
                                    new Message(MSG.view_configEdit_msg_2(), EnumSet.of(Message.Option.Transient)));
                            }
                        }
                    });
                }
            });

            selectItem.addChangedHandler(new ChangedHandler() {
                @Override
                public void onChanged(ChangedEvent changedEvent) {
                    Object value = changedEvent.getValue();
                    if (value != null) {
                        String stringValue = value.toString();
                        String[] memberPropertyNames = stringValue.split(",");
                        okButton.setDisabled(memberPropertyNames.length == 0);
                    }
                }
            });

            deleteForm.setFields(selectItem);
            deleteControlsLayout.addMember(deleteForm);
            deleteControlsLayout.addMember(okButton);

            buttonBar.addMember(deleteControlsLayout);
            layout.addMember(buttonBar);
        }

        CanvasItem canvasItem = buildComplexPropertyField(layout);
        canvasItem.setColSpan(3);
        canvasItem.setEndRow(true);
View Full Code Here

        // Now add rows containing the actual data (i.e. member property values).
        ListGridRecord[] rows = buildSummaryRecords(propertyList, propertyDefinitions);
        summaryTable.setData(rows);

        VLayout summaryTableHolder = new EnhancedVLayout();

        ToolStrip toolStrip = new ToolStrip();
        toolStrip.setWidth100();
        if (!propertyReadOnly) {
            IButton addRowButton = new EnhancedIButton();
            addRowButton.setWidth("40px");
            addRowButton.setIcon(Window.getImgURL(ImageManager.getAddIcon()));
            addRowButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    if (propertyList.getList().size() >= listMax) {
                        SC.say(MSG.view_configEdit_maxBoundsExceeded(String.valueOf(propertyDefinitionList.getMax())));
                        return;
                    }
                    displayMapEditor(summaryTable, errorPanel, null, propertyDefinitionList, propertyList,
                        memberPropertyDefinitionMap, null, mapReadOnly);
                }
            });
            toolStrip.addMember(addRowButton);
        }

        if (isListGridRecordCountValid(summaryTable.getRecords(), listMin, listMax)) {
            errorPanel.setVisible(false);
        } else {
            errorPanel.setVisible(true);
        }
        summaryTableHolder.setMembers(summaryTable, toolStrip, errorPanel);

        CanvasItem canvasItem = buildComplexPropertyField(summaryTableHolder);
        canvasItem.setColSpan(3);
        canvasItem.setEndRow(true);
View Full Code Here

    private CanvasItem buildListOfSimplesField(final PropertyDefinitionList propertyDefinitionList,
        final PropertyList propertyList) {
        Log.debug("Building list-of-simples field for " + propertyList + "...");

        EnhancedVLayout vLayout = new EnhancedVLayout();

        final DynamicForm listGrid = new DynamicForm();
        vLayout.addMember(listGrid);

        final SelectItem membersItem = new SelectItem(propertyList.getName());
        membersItem.setShowTitle(false);
        membersItem.setMultiple(true);
        membersItem.setMultipleAppearance(MultipleAppearance.GRID);
        membersItem.setWidth(220);
        membersItem.setHeight(60);
        LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
        membersItem.setValueMap(memberValueToIndexMap);
        listGrid.setItems(membersItem);

        if (!isReadOnly(propertyDefinitionList, propertyList)) {
            // List is not read-only - add footer with New and Delete buttons to allow user to add or remove members.
            ToolStrip footer = new ToolStrip();
            footer.setPadding(5);
            footer.setWidth100();
            footer.setMembersMargin(15);
            vLayout.addMember(footer);

            final IButton deleteButton = new EnhancedIButton(MSG.common_button_delete());
            deleteButton.setIcon(Window.getImgURL(ImageManager.getRemoveIcon()));
            deleteButton.setTooltip(MSG.view_configEdit_tooltip_1());
            deleteButton.setDisabled(true);
            deleteButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    final String[] selectedValues = membersItem.getValues();
                    final String noun = (selectedValues.length == 1) ? MSG.common_label_item() : MSG
                        .common_label_items();
                    String message = MSG.view_configEdit_confirm_3(Integer.toString(selectedValues.length), noun);
                    if (propertyList.getList().size() <= propertyDefinitionList.getMin()) {
                        SC.say("You cannot delete this entry because the minimum size bounds has been met: "
                            + propertyDefinitionList.getMin());
                    } else {
                        SC.ask(message, new BooleanCallback() {
                            public void execute(Boolean confirmed) {
                                if (confirmed) {
                                    for (int i = selectedValues.length - 1; i >= 0; i--) {
                                        String selectedValue = selectedValues[i];
                                        int index = Integer.valueOf(selectedValue);
                                        propertyList.getList().remove(index);

                                        // Rebuild the select item options.
                                        LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
                                        membersItem.setValueMap(memberValueToIndexMap);

                                        deleteButton.disable();

                                        firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
                                        CoreGUI.getMessageCenter().notify(
                                            new Message(MSG.view_configEdit_msg_3(
                                                Integer.toString(selectedValues.length), noun), EnumSet
                                                .of(Message.Option.Transient)));
                                    }
                                }
                            }
                        });
                    }
                }
            });
            footer.addMember(deleteButton);

            membersItem.addChangedHandler(new ChangedHandler() {
                @Override
                public void onChanged(ChangedEvent changedEvent) {
                    String[] selectedValues = membersItem.getValues();
                    int count = selectedValues.length;
                    deleteButton.setDisabled(count < 1);
                }
            });

            final IButton newButton = new EnhancedIButton(MSG.common_button_new());
            newButton.setIcon(Window.getImgURL(ImageManager.getAddIcon()));
            newButton.setTooltip(MSG.view_configEdit_tooltip_2());
            newButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                public void onClick(ClickEvent clickEvent) {

                    if (propertyList.getList().size() >= propertyDefinitionList.getMax()) {
                        SC.say(MSG.view_configEdit_maxBoundsExceeded(String.valueOf(propertyDefinitionList.getMax())));
                    } else {
                        final Window popup = createPopup(MSG.view_configEdit_addItem(), 400, 150);

                        VLayout vLayout = new VLayout();
                        vLayout.setMargin(10);

                        HTMLFlow description = new HTMLFlow(propertyDefinitionList.getDescription());
                        vLayout.addMember(description);

                        final DynamicForm form = new DynamicForm();

                        PropertyDefinitionSimple memberPropertyDefinitionSimple = (PropertyDefinitionSimple) propertyDefinitionList
                            .getMemberDefinition();
                        final String propertyName = memberPropertyDefinitionSimple.getName();
                        final PropertySimple newMemberPropertySimple = new PropertySimple(propertyName, null);

                        FormItem simpleField = buildSimpleField(memberPropertyDefinitionSimple, newMemberPropertySimple);
                        simpleField.setTitle(memberPropertyDefinitionSimple.getDisplayName());
                        simpleField.setShowTitle(true);
                        simpleField.setAlign(Alignment.CENTER);
                        simpleField.setDisabled(false);
                        simpleField.setRequired(true);
                        simpleField.setEndRow(true);

                        SpacerItem spacer = new SpacerItem();
                        spacer.setHeight(9);

                        form.setItems(simpleField, spacer);
                        vLayout.addMember(form);

                        final IButton okButton = new EnhancedIButton(MSG.common_button_ok(), ButtonColor.BLUE);
                        okButton.disable();
                        okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                            public void onClick(ClickEvent clickEvent) {
                                propertyList.add(newMemberPropertySimple);

                                // Rebuild the select item options.
                                LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
                                membersItem.setValueMap(memberValueToIndexMap);

                                firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
                                CoreGUI.getMessageCenter().notify(
                                    new Message(MSG.view_configEdit_msg_4(), EnumSet.of(Message.Option.Transient)));

                                popup.destroy();
                            }
                        });

                        form.addItemChangedHandler(new ItemChangedHandler() {
                            public void onItemChanged(ItemChangedEvent itemChangedEvent) {
                                Object newValue = itemChangedEvent.getNewValue();
                                newMemberPropertySimple.setValue(newValue);

                                // Only enable the OK button, allowing the user to add the property to the map, if the
                                // property is valid.
                                boolean isValid = form.validate();
                                okButton.setDisabled(!isValid);
                            }
                        });

                        final IButton cancelButton = new EnhancedIButton(MSG.common_button_cancel());
                        cancelButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                            public void onClick(ClickEvent clickEvent) {
                                popup.destroy();
                            }
                        });

                        ToolStrip buttonBar = new ToolStrip();
                        buttonBar.setPadding(5);
                        buttonBar.setWidth100();
                        buttonBar.setMembersMargin(15);
                        buttonBar.setAlign(Alignment.CENTER);
                        buttonBar.setMembers(okButton, cancelButton);

                        vLayout.addMember(buttonBar);

                        popup.addItem(vLayout);
                        popup.show();

                        simpleField.focusInItem();
View Full Code Here

            .deepCopy(true);

        final String title = (mapReadOnly) ? MSG.view_configEdit_viewRow() : MSG.view_configEdit_editRow();
        final Window popup = createPopup(title, 800, 600);

        final EnhancedVLayout layout = new EnhancedVLayout();
        layout.setHeight100();
        layout.setMargin(8);

        final DynamicForm childForm = buildPropertiesForm(memberDefinitions, workingMap);
        childForm.setHeight100();
        layout.addMember(childForm);

        ToolStrip buttonBar = new ToolStrip();
        buttonBar.setPadding(5);
        buttonBar.setWidth100();
        buttonBar.setMembersMargin(15);
        buttonBar.setAlign(Alignment.CENTER);

        final IButton okButton = new EnhancedIButton(MSG.common_button_ok(), ButtonColor.BLUE);
        if (!mapReadOnly) {
            okButton.disable();
        }
        okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                if (!mapReadOnly) {
                    if (!childForm.validate()) {
                        okButton.disable();
                        return;
                    }
                    if (newRow) {
                        propertyList.add(workingMap);
                        int index = propertyList.getList().size() - 1;
                        PropertyMapListGridRecord record = new PropertyMapListGridRecord(workingMap, index,
                            memberDefinitions);
                        summaryTable.addData(record);
                    } else {
                        mergePropertyMap(workingMap, memberMap, memberDefinitions);
                        existingRecord.refresh();
                        summaryTable.updateData(existingRecord);
                    }
                    boolean listGridRecordCountValid = isListGridRecordCountValid(summaryTable.getRecords(),
                        propertyDefinitionList.getMin(), propertyDefinitionList.getMax());
                    if (errorPanel.isVisible() && listGridRecordCountValid) {
                        errorPanel.setVisible(false);
                    }
                    firePropertyChangedEvent(propertyList, propertyDefinitionList, listGridRecordCountValid);
                    summaryTable.redraw();
                }

                //reset the custom blur event handling - we're destroying the new form here
                blurUnsetItem = null;
                blurValueItem = null;

                layout.destroy();
                popup.destroy();
            }
        });

        // Only enable the OK button if all properties are valid.
        childForm.addItemChangedHandler(new ItemChangedHandler() {
            public void onItemChanged(ItemChangedEvent itemChangedEvent) {
                // TODO (ips, 03/14/11): Ideally, we would validate the form here, but it's preventing boolean prop
                //                       radio buttons from being selectable, most likely due to a SmartGWT bug.
                //okButton.setDisabled(!childForm.validate());
                okButton.setDisabled(false);
            }
        });
        buttonBar.addMember(okButton);

        if (!mapReadOnly) {
            final IButton cancelButton = new IButton(MSG.common_button_cancel());
            cancelButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    layout.destroy();
                    popup.destroy();
                }
            });
            buttonBar.addMember(cancelButton);
        }

        //reset the custom blur event handling - we're creating a new form here
        blurUnsetItem = null;
        blurValueItem = null;

        layout.addMember(buttonBar);
        popup.addItem(layout);
        popup.show();
    }
View Full Code Here

TOP

Related Classes of org.rhq.coregui.client.util.enhanced.EnhancedVLayout

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.