001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.hbtop.screen.field;
019
020import java.util.ArrayList;
021import java.util.EnumMap;
022import java.util.List;
023import java.util.Objects;
024
025import org.apache.hadoop.hbase.hbtop.field.Field;
026import org.apache.hadoop.hbase.hbtop.screen.ScreenView;
027import org.apache.yetus.audience.InterfaceAudience;
028
029
030/**
031 * The presentation logic for the field screen.
032 */
033@InterfaceAudience.Private
034public class FieldScreenPresenter {
035
036  @FunctionalInterface
037  public interface ResultListener {
038    void accept(Field sortField, List<Field> fields, EnumMap<Field, Boolean> fieldDisplayMap);
039  }
040
041  private final FieldScreenView fieldScreenView;
042  private Field sortField;
043  private final List<Field> fields;
044  private final EnumMap<Field, Boolean> fieldDisplayMap;
045  private final ResultListener resultListener;
046  private final ScreenView nextScreenView;
047
048  private final int headerMaxLength;
049  private final int descriptionMaxLength;
050
051  private int currentPosition;
052  private boolean moveMode;
053
054  public FieldScreenPresenter(FieldScreenView fieldScreenView, Field sortField, List<Field> fields,
055    EnumMap<Field, Boolean> fieldDisplayMap, ResultListener resultListener,
056    ScreenView nextScreenView) {
057    this.fieldScreenView = Objects.requireNonNull(fieldScreenView);
058    this.sortField = Objects.requireNonNull(sortField);
059    this.fields = new ArrayList<>(Objects.requireNonNull(fields));
060    this.fieldDisplayMap = new EnumMap<>(Objects.requireNonNull(fieldDisplayMap));
061    this.resultListener = Objects.requireNonNull(resultListener);
062    this.nextScreenView = Objects.requireNonNull(nextScreenView);
063
064    int headerLength = 0;
065    int descriptionLength = 0;
066    for (int i = 0; i < fields.size(); i ++) {
067      Field field = fields.get(i);
068
069      if (field == sortField) {
070        currentPosition = i;
071      }
072
073      if (headerLength < field.getHeader().length()) {
074        headerLength = field.getHeader().length();
075      }
076
077      if (descriptionLength < field.getDescription().length()) {
078        descriptionLength = field.getDescription().length();
079      }
080    }
081
082    headerMaxLength = headerLength;
083    descriptionMaxLength = descriptionLength;
084  }
085
086  public void init() {
087    fieldScreenView.hideCursor();
088    fieldScreenView.clearTerminal();
089    fieldScreenView.showFieldScreen(sortField.getHeader(), fields, fieldDisplayMap,
090      currentPosition, headerMaxLength, descriptionMaxLength, moveMode);
091    fieldScreenView.refreshTerminal();
092  }
093
094  public void arrowUp() {
095    if (currentPosition > 0) {
096      currentPosition -= 1;
097
098      if (moveMode) {
099        Field tmp = fields.remove(currentPosition);
100        fields.add(currentPosition + 1, tmp);
101      }
102
103      showField(currentPosition);
104      showField(currentPosition + 1);
105      fieldScreenView.refreshTerminal();
106    }
107  }
108
109  public void arrowDown() {
110    if (currentPosition < fields.size() - 1) {
111      currentPosition += 1;
112
113      if (moveMode) {
114        Field tmp = fields.remove(currentPosition - 1);
115        fields.add(currentPosition, tmp);
116      }
117
118      showField(currentPosition);
119      showField(currentPosition - 1);
120      fieldScreenView.refreshTerminal();
121    }
122  }
123
124  public void pageUp() {
125    if (currentPosition > 0 && !moveMode) {
126      int previousPosition = currentPosition;
127      currentPosition = 0;
128      showField(previousPosition);
129      showField(currentPosition);
130      fieldScreenView.refreshTerminal();
131    }
132  }
133
134  public void pageDown() {
135    if (currentPosition < fields.size() - 1  && !moveMode) {
136      int previousPosition = currentPosition;
137      currentPosition = fields.size() - 1;
138      showField(previousPosition);
139      showField(currentPosition);
140      fieldScreenView.refreshTerminal();
141    }
142  }
143
144  public void turnOnMoveMode() {
145    moveMode = true;
146    showField(currentPosition);
147    fieldScreenView.refreshTerminal();
148  }
149
150  public void turnOffMoveMode() {
151    moveMode = false;
152    showField(currentPosition);
153    fieldScreenView.refreshTerminal();
154  }
155
156  public void switchFieldDisplay() {
157    if (!moveMode) {
158      Field field = fields.get(currentPosition);
159      fieldDisplayMap.put(field, !fieldDisplayMap.get(field));
160      showField(currentPosition);
161      fieldScreenView.refreshTerminal();
162    }
163  }
164
165  private void showField(int pos) {
166    Field field = fields.get(pos);
167    fieldScreenView.showField(pos, field, fieldDisplayMap.get(field), pos == currentPosition,
168      headerMaxLength, descriptionMaxLength, moveMode);
169  }
170
171  public void setSortField() {
172    if (!moveMode) {
173      Field newSortField = fields.get(currentPosition);
174      if (newSortField != this.sortField) {
175        this.sortField = newSortField;
176        fieldScreenView.showScreenDescription(sortField.getHeader());
177        fieldScreenView.refreshTerminal();
178      }
179    }
180  }
181
182  public ScreenView transitionToNextScreen() {
183    resultListener.accept(sortField, fields, fieldDisplayMap);
184    return nextScreenView;
185  }
186}