summaryrefslogtreecommitdiff
path: root/login/src/com/google/gct/login/ui/GoogleLoginUsersPanel.java
blob: 6536283ca657719687830af698b49698da205d2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.gct.login.ui;

import com.google.gct.login.CredentialedUser;
import com.google.gct.login.GoogleLogin;
import com.intellij.ide.BrowserUtil;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBScrollPane;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.LinkedHashMap;

/**
 * The Google Login Panel that displays the currently logged in users and buttons to
 * add a new user and sign out a logged in user.
 */
public class GoogleLoginUsersPanel extends JPanel implements ListSelectionListener {
  private static final String PLAY_CONSOLE_URL = "https://play.google.com/apps/publish/#ProfilePlace";
  private static final String CLOUD_CONSOLE_URL = "https://console.developers.google.com/accountsettings";
  private final static String LEARN_MORE_URL = "https://developers.google.com/cloud/devtools/android_studio_templates/";
  private JBList list;
  private DefaultListModel listModel;
  private static final int MAX_VISIBLE_ROW_COUNT = 3;
  private static final String addAccountString = "Add Account";
  private static final String signInString = "Sign In";
  private static final String signOutString = "Sign Out";
  private JButton signOutButton;
  private JButton addAccountButton;
  private boolean valueChanged = false;

  public GoogleLoginUsersPanel() {
    super(new BorderLayout());

    int indexToSelect = initializeUsers();
    final UsersListCellRenderer usersListCellRenderer = new UsersListCellRenderer();

    //Create the list that displays the users and put it in a scroll pane.
    list = new JBList(listModel) {
      @Override
      public Dimension getPreferredScrollableViewportSize() {
        int numUsers = listModel.size();
        Dimension superPreferredSize = super.getPreferredScrollableViewportSize();
        if(numUsers <= 1) {
          return superPreferredSize;
        }

        if(GoogleLogin.getInstance().getActiveUser() == null){
          return superPreferredSize;
        } else if(!isActiveUserInVisibleArea()) {
          return superPreferredSize;
        } else {
          // if there is an active user in the visible area
          int usersToShow = numUsers > MAX_VISIBLE_ROW_COUNT ? MAX_VISIBLE_ROW_COUNT : numUsers;
          int scrollHeight = ((usersToShow - 1) *  usersListCellRenderer.getMainPanelHeight())
            + usersListCellRenderer.getActivePanelHeight();
          return new Dimension((int)superPreferredSize.getWidth(), scrollHeight);
        }
      }
    };

    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    list.setSelectedIndex(indexToSelect);
    list.addListSelectionListener(this);
    list.setVisibleRowCount(getVisibleRowCount());
    list.setCellRenderer(usersListCellRenderer);
    JBScrollPane listScrollPane = new JBScrollPane(list);

    list.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent mouseEvent) {
        list.updateUI();

        if(listModel.getSize() == 1 && (listModel.get(0) instanceof NoUsersListItem)) {
          // When there are no users available
          if(usersListCellRenderer.inLearnMoreUrl(mouseEvent.getPoint())){
            BrowserUtil.browse(LEARN_MORE_URL);
          }
        } else {
          // When users are available
          if(!valueChanged) {
            // Clicking on an already active user
            int index = list.locationToIndex(mouseEvent.getPoint());
            if (index >= 0) {
              boolean inPlayUrl = usersListCellRenderer.inPlayConsoleUrl(mouseEvent.getPoint(), index);
              if(inPlayUrl){
                BrowserUtil.browse(PLAY_CONSOLE_URL);
              } else {
                boolean inCloudUrl = usersListCellRenderer.inCloudConsoleUrl(mouseEvent.getPoint(), index);
                if(inCloudUrl) {
                  BrowserUtil.browse(CLOUD_CONSOLE_URL);
                }
              }
            }
          }
        }
        valueChanged = false;
      }
    });

    list.addMouseMotionListener(new MouseMotionListener() {
      @Override
      public void mouseMoved(MouseEvent mouseEvent) {
        // Determine if the user under the cursor is an active user, a non-active user or a non-user
        int index = list.locationToIndex(mouseEvent.getPoint());
        if (index >= 0) {
          // If current object is the non-user list item, use default cursor
          Object currentObject = listModel.get(index);
          if(currentObject instanceof NoUsersListItem) {
            if(usersListCellRenderer.inLearnMoreUrl(mouseEvent.getPoint())) {
              list.setCursor(new Cursor(Cursor.HAND_CURSOR));
            } else {
              list.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
            return;
          }

          if (((UsersListItem)currentObject).isActiveUser()) {
            // Active user
            boolean inPlayUrl = usersListCellRenderer.inPlayConsoleUrl(mouseEvent.getPoint(), index);
            boolean inCloudUrl = usersListCellRenderer.inCloudConsoleUrl(mouseEvent.getPoint(), index);
            if(inPlayUrl || inCloudUrl){
              list.setCursor(new Cursor(Cursor.HAND_CURSOR));
            } else {
              list.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
          } else {
            // For non-active user
            list.setCursor(new Cursor(Cursor.HAND_CURSOR));
          }
        }
      }

      @Override
      public void mouseDragged(MouseEvent e) {
      }
    });

    boolean noUsersAvailable = (listModel.getSize() == 1) && (listModel.get(0) instanceof NoUsersListItem);
    addAccountButton = new JButton(noUsersAvailable ? signInString : addAccountString);
    AddAccountListener addAccountListener = new AddAccountListener();
    addAccountButton.addActionListener(addAccountListener);
    addAccountButton.setHorizontalAlignment(SwingConstants.LEFT);

    signOutButton = new JButton(signOutString);
    signOutButton.addActionListener(new SignOutListener());

    if(list.isSelectionEmpty()) {
      signOutButton.setEnabled(false);
    } else {
      // If list contains the NoUsersListItem place holder
      // sign out button should be hidden
      if(noUsersAvailable) {
        signOutButton.setVisible(false);
      } else {
        signOutButton.setEnabled(true);
      }
    }

    //Create a panel to hold the buttons
    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
    buttonPane.add(addAccountButton);
    buttonPane.add(Box.createHorizontalGlue());
    buttonPane.add(signOutButton);
    buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

    add(listScrollPane, BorderLayout.CENTER);
    add(buttonPane, BorderLayout.PAGE_END);
  }

  /**
   * The action listener for {@code signOutButton}
   */
  class SignOutListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      GoogleLogin.getInstance().logOut();
    }
  }

  /**
   * The action listener for {@code addAccountButton}
   */
  class AddAccountListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      GoogleLogin.getInstance().logIn();
    }
  }

  //This method is required by ListSelectionListener.
  @Override
  public void valueChanged(ListSelectionEvent e) {
    valueChanged = true;
    if (e.getValueIsAdjusting() == false) {
      if (list.getSelectedIndex() == -1) {
        signOutButton.setEnabled(false);
      } else {
        signOutButton.setEnabled(true);

        // Make newly selected value the active value
        UsersListItem selectedUser = (UsersListItem)listModel.get(list.getSelectedIndex());
        if(!selectedUser.isActiveUser()) {
          GoogleLogin.getInstance().setActiveUser(selectedUser.getUserEmail());
        }
      }
    }
  }

  public JBList getList() {
    return list;
  }

  private int initializeUsers() {
    LinkedHashMap<String, CredentialedUser> allUsers = GoogleLogin.getInstance().getAllUsers();
    listModel = new DefaultListModel();

    int activeUserIndex = allUsers.size();
    for(CredentialedUser aUser : allUsers.values()) {
      listModel.addElement(new UsersListItem(aUser));
      if(aUser.isActive()) {
        activeUserIndex = listModel .getSize() - 1;
      }
    }

    if(listModel.getSize() == 0) {
      // Add no user panel
      listModel.addElement(NoUsersListItem.INSTANCE);
    }

    return activeUserIndex;
  }

  private int getVisibleRowCount(){
    if (listModel == null) {
      return 0;
    }

    int size = listModel.getSize();
    if(size >= MAX_VISIBLE_ROW_COUNT) {
      return MAX_VISIBLE_ROW_COUNT;
    } else if (size == 0) {
      return 3;
    } else {
      return  size;
    }
  }

  private boolean isActiveUserInVisibleArea() {
    int max = listModel.getSize() < MAX_VISIBLE_ROW_COUNT ?
      listModel.getSize() : MAX_VISIBLE_ROW_COUNT;

    for(int i = 0; i < max; i++){
      if(((UsersListItem)listModel.get(i)).isActiveUser()) {
        return true;
      }
    }
    return false;
  }
}