View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.hbtop.terminal.impl;
19  
20  import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.clearRemainingLine;
21  import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.color;
22  import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.cursor;
23  import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.moveCursor;
24  import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.normal;
25  
26  import java.io.PrintWriter;
27  
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.hbtop.terminal.Attributes;
30  import org.apache.hadoop.hbase.hbtop.terminal.CursorPosition;
31  
32  /**
33   * Represents a buffer of the terminal screen for double-buffering.
34   */
35  @InterfaceAudience.Private
36  public class ScreenBuffer {
37    private int columns;
38    private int rows;
39  
40    private Cell[][] buffer;
41    private Cell[][] physical;
42  
43    private boolean cursorVisible;
44    private int cursorColumn;
45    private int cursorRow;
46  
47    public void reallocate(int columns, int rows) {
48      buffer = new Cell[columns][rows];
49      physical = new Cell[columns][rows];
50  
51      for (int row = 0; row < rows; row++) {
52        for (int column = 0; column < columns; column++) {
53          buffer[column][row] = new Cell();
54  
55          physical[column][row] = new Cell();
56          physical[column][row].unset();
57        }
58      }
59  
60      this.columns = columns;
61      this.rows = rows;
62    }
63  
64    public void clear() {
65      for (int row = 0; row < rows; row++) {
66        for (int col = 0; col < columns; col++) {
67          buffer[col][row].reset();
68        }
69      }
70    }
71  
72    public void flush(PrintWriter output) {
73      StringBuilder sb = new StringBuilder();
74  
75      sb.append(normal());
76      Attributes attributes = new Attributes();
77      for (int row = 0; row < rows; row++) {
78        flushRow(row, sb, attributes);
79      }
80  
81      if (cursorVisible && cursorRow >= 0 && cursorColumn >= 0 && cursorRow < rows &&
82        cursorColumn < columns) {
83        sb.append(cursor(true));
84        sb.append(moveCursor(cursorColumn, cursorRow));
85      } else {
86        sb.append(cursor(false));
87      }
88  
89      output.write(sb.toString());
90      output.flush();
91    }
92  
93    private void flushRow(int row, StringBuilder sb, Attributes lastAttributes) {
94      int lastColumn = -1;
95      for (int column = 0; column < columns; column++) {
96        Cell cell = buffer[column][row];
97        Cell pCell = physical[column][row];
98  
99        if (!cell.equals(pCell)) {
100         if (lastColumn != column - 1 || lastColumn == -1) {
101           sb.append(moveCursor(column, row));
102         }
103 
104         if (cell.isEndOfLine()) {
105           for (int i = column; i < columns; i++) {
106             physical[i][row].set(buffer[i][row]);
107           }
108 
109           sb.append(clearRemainingLine());
110           lastAttributes.reset();
111           return;
112         }
113 
114         if (!cell.getAttributes().equals(lastAttributes)) {
115           sb.append(color(cell.getForegroundColor(), cell.getBackgroundColor(), cell.isBold(),
116             cell.isReverse(), cell.isBlink(), cell.isUnderline()));
117         }
118 
119         sb.append(cell.getChar());
120 
121         lastColumn = column;
122         lastAttributes.set(cell.getAttributes());
123 
124         physical[column][row].set(cell);
125       }
126     }
127   }
128 
129   public CursorPosition getCursorPosition() {
130     return new CursorPosition(cursorColumn, cursorRow);
131   }
132 
133   public void setCursorPosition(int column, int row) {
134     cursorVisible = true;
135     cursorColumn = column;
136     cursorRow = row;
137   }
138 
139   public void hideCursor() {
140     cursorVisible = false;
141   }
142 
143   public void putString(int column, int row, String string, Attributes attributes) {
144     int i = column;
145     for (int j = 0; j < string.length(); j++) {
146       char ch = string.charAt(j);
147       putChar(i, row, ch, attributes);
148       i += 1;
149       if (i == columns) {
150         break;
151       }
152     }
153   }
154 
155   public void putChar(int column, int row, char ch, Attributes attributes) {
156     if (column >= 0 && column < columns && row >= 0 && row < rows) {
157       buffer[column][row].setAttributes(attributes);
158       buffer[column][row].setChar(ch);
159     }
160   }
161 
162   public void endOfLine(int column, int row) {
163     if (column >= 0 && column < columns && row >= 0 && row < rows) {
164       buffer[column][row].endOfLine();
165       for (int i = column + 1; i < columns; i++) {
166         buffer[i][row].reset();
167       }
168     }
169   }
170 }