📄 autohidemanager.java
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.ui.experimental;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import edu.tsinghua.lumaqq.ui.MainShell;
import edu.tsinghua.lumaqq.utils.OptionUtil;
/**
* <pre>
* 监听主窗口位置,条件满足的时候自动隐藏窗口
*
* 目前在Windows没有问题,但是在linux还是很诡异,所以目前这个类没有用到
* </pre>
*
* @author 马若劼
*/
public class AutoHideManager implements ControlListener, MouseTrackListener, ShellListener {
/**
* <pre>
* 用来检查鼠标的位置,因为我目前是想不出什么更好的办法
* </pre>
*
* @author 马若劼
*/
private class MouseLocationDetector implements Runnable {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
if(needHide()) {
Point loc = display.getCursorLocation();
if(!currentBound.contains(loc)) {
hideShell();
showRibbon();
} else if(needHide()) {
display.timerExec(2000, this);
}
}
}
}
private Shell shell;
private Display display;
private Shell ribbon;
private Rectangle currentBound, showBound, hideBound, historyBound, clientArea;
private Rectangle ribbonShowBound;
private OptionUtil options;
private MouseLocationDetector detector;
private int hide;
/**
* 构造函数
*
* @param main
* MainShell
*/
public AutoHideManager(MainShell main) {
options = OptionUtil.getInstance();
detector = new MouseLocationDetector();
hide = SWT.NONE;
hideBound = new Rectangle(0, 0, 0, 0);
ribbonShowBound = new Rectangle(0, 0, 0, 0);
shell = main.getShell();
display = main.getDisplay();
shell.addControlListener(this);
shell.addShellListener(this);
ribbon = new Shell(display, SWT.ON_TOP | SWT.NO_TRIM);
ribbon.addMouseTrackListener(this);
historyBound = showBound = shell.getBounds();
}
/**
* @return true表示需要隐藏
*/
public synchronized boolean needHide() {
return hide != SWT.NONE;
}
/**
* 这是隐藏标志
*
* @param h
* 隐藏标志
*/
private synchronized void setHide(int h) {
hide = h;
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
*/
public void controlMoved(ControlEvent e) {
autoHide();
}
/**
* 判断情况,如果需要,则自动隐藏
*/
private void autoHide() {
currentBound = shell.getBounds();
if(currentBound.equals(showBound)) return;
clientArea = display.getClientArea();
// 如果隐藏标志没有变化,返回
int newHide = checkCondition(currentBound, clientArea);
if(hide == newHide) {
if(newHide == SWT.NONE)
historyBound = currentBound;
return;
}
// 如果从隐藏到不隐藏,恢复窗口原始大小
if(needHide() && newHide == SWT.NONE)
shell.setSize(historyBound.width, historyBound.height);
// 设置新的隐藏标志,采取相应动作
setHide(newHide);
switch(hide) {
case SWT.RIGHT:
hideRight();
break;
case SWT.LEFT:
hideLeft();
break;
case SWT.TOP:
hideTop();
break;
default:
ribbon.setVisible(false);
break;
}
}
/**
* 在顶部隐藏
*/
private void hideTop() {
showBound.x = currentBound.x;
showBound.y = 0;
showBound.width = currentBound.width;
showBound.height = currentBound.height;
hideBound.x = currentBound.x;
hideBound.y = -currentBound.height - 1;
hideBound.width = currentBound.width;
hideBound.height = currentBound.height;
ribbonShowBound.x = currentBound.x;
ribbonShowBound.y = 0;
ribbonShowBound.width = currentBound.width;
ribbonShowBound.height = 1;
hideShell();
showRibbon();
}
/**
* 在左边隐藏
*/
private void hideLeft() {
showBound.x = 0;
showBound.y = 0;
showBound.width = currentBound.width;
showBound.height = clientArea.height;
hideBound.x = -currentBound.width - 1;
hideBound.y = 0;
hideBound.width = currentBound.width;
hideBound.height = clientArea.height;
ribbonShowBound.x = 0;
ribbonShowBound.y = 0;
ribbonShowBound.width = 1;
ribbonShowBound.height = clientArea.height;
hideShell();
showRibbon();
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
*/
public void controlResized(ControlEvent e) {
}
/**
* 在右边隐藏
* @param shellBound
* @param clientArea
*/
private void hideRight() {
showBound.x = clientArea.width - currentBound.width;
showBound.y = 0;
showBound.width = currentBound.width;
showBound.height = clientArea.height;
hideBound.x = clientArea.width + 1;
hideBound.y = 0;
hideBound.width = currentBound.width;
hideBound.height = clientArea.height;
ribbonShowBound.x = clientArea.width - 1;
ribbonShowBound.y = 0;
ribbonShowBound.width = 1;
ribbonShowBound.height = clientArea.height;
hideShell();
showRibbon();
}
/**
* 隐藏被托管的Shell
*/
private void hideShell() {
shell.setBounds(hideBound);
shell.setVisible(false);
}
/**
* 显示dummy shell
*/
private void showRibbon() {
ribbon.setBounds(ribbonShowBound);
ribbon.setVisible(true);
}
/**
* 显示受托管的窗口
*/
private void showShell() {
shell.setBounds(showBound);
shell.setVisible(true);
shell.setActive();
}
/**
* 隐藏dummy shell
*/
private void hideRibbon() {
ribbon.setVisible(false);
}
/**
* 判断当前是否需要自动隐藏窗口
*
* @param bound
* 窗口的位置和大小
* @param clientArea
* 显示器的大小
* @return
* 如果需要在左边隐藏,返回SWT.LEFT,等等,如果不需要隐藏,返回SWT.NONE
* 但是我们不会隐藏到底部
*/
private int checkCondition(Rectangle bound, Rectangle clientArea) {
if(bound.x + bound.width > clientArea.width)
return SWT.RIGHT;
else if(bound.x < 0)
return SWT.LEFT;
else if(bound.y < 0)
return SWT.TOP;
else
return SWT.NONE;
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
*/
public void mouseEnter(MouseEvent e) {
autoShow();
}
/**
* 显示窗口
*/
public void autoShow() {
hideRibbon();
showShell();
display.timerExec(2000, detector);
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
*/
public void mouseExit(MouseEvent e) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
*/
public void mouseHover(MouseEvent e) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(ShellEvent arg0) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt.events.ShellEvent)
*/
public void shellClosed(ShellEvent arg0) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(ShellEvent arg0) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeiconified(ShellEvent e) {
if(needHide()) {
hideShell();
showRibbon();
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellIconified(ShellEvent e) {
if(options.isAutoHide())
shell.setVisible(false);
}
/**
* @return 没有自动隐藏前的窗口位置
*/
public Rectangle getHistoryBound() {
return historyBound;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -