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;
024import org.apache.hadoop.hbase.hbtop.field.Field;
025import org.apache.hadoop.hbase.hbtop.screen.ScreenView;
026import org.apache.yetus.audience.InterfaceAudience;
027
028/**
029 * The presentation logic for the field screen.
030 */
031@InterfaceAudience.Private
032public class FieldScreenPresenter {
033
034  @FunctionalInterface
035  public interface ResultListener {
036    void accept(Field sortField, List<Field> fields, EnumMap<Field, Boolean> fieldDisplayMap);
037  }
038
039  private final FieldScreenView fieldScreenView;
040  private Field sortField;
041  private final List<Field> fields;
042  private final EnumMap<Field, Boolean> fieldDisplayMap;
043  private final ResultListener resultListener;
044  private final ScreenView nextScreenView;
045
046  private final int headerMaxLength;
047  private final int descriptionMaxLength;
048
049  private int currentPosition;
050  private boolean moveMode;
051
052  public FieldScreenPresenter(FieldScreenView fieldScreenView, Field sortField, List<Field> fields,
053    EnumMap<Field, Boolean> fieldDisplayMap, ResultListener resultListener,
054    ScreenView nextScreenView) {
055    this.fieldScreenView = Objects.requireNonNull(fieldScreenView);
056    this.sortField = Objects.requireNonNull(sortField);
057    this.fields = new ArrayList<>(Objects.requireNonNull(fields));
058    this.fieldDisplayMap = new EnumMap<>(Objects.requireNonNull(fieldDisplayMap));
059    this.resultListener = Objects.requireNonNull(resultListener);
060    this.nextScreenView = Objects.requireNonNull(nextScreenView);
061
062    int headerLength = 0;
063    int descriptionLength = 0;
064    for (int i = 0; i < fields.size(); i++) {
065      Field field = fields.get(i);
066
067      if (field == sortField) {
068        currentPosition = i;
069      }
070
071      if (headerLength < field.getHeader().length()) {
072        headerLength = field.getHeader().length();
073      }
074
075      if (descriptionLength < field.getDescription().length()) {
076        descriptionLength = field.getDescription().length();
077      }
078    }
079
080    headerMaxLength = headerLength;
081    descriptionMaxLength = descriptionLength;
082  }
083
084  public void init() {
085    fieldScreenView.hideCursor();
086    fieldScreenView.clearTerminal();
087    fieldScreenView.showFieldScreen(sortField.getHeader(), fields, fieldDisplayMap, currentPosition,
088      headerMaxLength, descriptionMaxLength, moveMode);
089    fieldScreenView.refreshTerminal();
090  }
091
092  public void arrowUp() {
093    if (currentPosition > 0) {
094      currentPosition -= 1;
095
096      if (moveMode) {
097        Field tmp = fields.remove(currentPosition);
098        fields.add(currentPosition + 1, tmp);
099      }
100
101      showField(currentPosition);
102      showField(currentPosition + 1);
103      fieldScreenView.refreshTerminal();
104    }
105  }
106
107  public void arrowDown() {
108    if (currentPosition < fields.size() - 1) {
109      currentPosition += 1;
110
111      if (moveMode) {
112        Field tmp = fields.remove(currentPosition - 1);
113        fields.add(currentPosition, tmp);
114      }
115
116      showField(currentPosition);
117      showField(currentPosition - 1);
118      fieldScreenView.refreshTerminal();
119    }
120  }
121
122  public void pageUp() {
123    if (currentPosition > 0 && !moveMode) {
124      int previousPosition = currentPosition;
125      currentPosition = 0;
126      showField(previousPosition);
127      showField(currentPosition);
128      fieldScreenView.refreshTerminal();
129    }
130  }
131
132  public void pageDown() {
133    if (currentPosition < fields.size() - 1 && !moveMode) {
134      int previousPosition = currentPosition;
135      currentPosition = fields.size() - 1;
136      showField(previousPosition);
137      showField(currentPosition);
138      fieldScreenView.refreshTerminal();
139    }
140  }
141
142  public void turnOnMoveMode() {
143    moveMode = true;
144    showField(currentPosition);
145    fieldScreenView.refreshTerminal();
146  }
147
148  public void turnOffMoveMode() {
149    moveMode = false;
150    showField(currentPosition);
151    fieldScreenView.refreshTerminal();
152  }
153
154  public void switchFieldDisplay() {
155    if (!moveMode) {
156      Field field = fields.get(currentPosition);
157      fieldDisplayMap.put(field, !fieldDisplayMap.get(field));
158      showField(currentPosition);
159      fieldScreenView.refreshTerminal();
160    }
161  }
162
163  private void showField(int pos) {
164    Field field = fields.get(pos);
165    fieldScreenView.showField(pos, field, fieldDisplayMap.get(field), pos == currentPosition,
166      headerMaxLength, descriptionMaxLength, moveMode);
167  }
168
169  public void setSortField() {
170    if (!moveMode) {
171      Field newSortField = fields.get(currentPosition);
172      if (newSortField != this.sortField) {
173        this.sortField = newSortField;
174        fieldScreenView.showScreenDescription(sortField.getHeader());
175        fieldScreenView.refreshTerminal();
176      }
177    }
178  }
179
180  public ScreenView transitionToNextScreen() {
181    resultListener.accept(sortField, fields, fieldDisplayMap);
182    return nextScreenView;
183  }
184}