Java tutorial
/* * 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; import static edu.tsinghua.lumaqq.resource.Messages.*; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.ViewForm; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.ShellListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.ColorDialog; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FontDialog; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Sash; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import edu.tsinghua.lumaqq.LumaQQ; import edu.tsinghua.lumaqq.events.IFaceSelectionListener; import edu.tsinghua.lumaqq.models.User; import edu.tsinghua.lumaqq.qq.Util; import edu.tsinghua.lumaqq.qq.beans.FontStyle; import edu.tsinghua.lumaqq.qq.beans.NormalIM; import edu.tsinghua.lumaqq.qq.beans.NormalIMHeader; import edu.tsinghua.lumaqq.record.IKeyConstants; import edu.tsinghua.lumaqq.record.RecordEntry; import edu.tsinghua.lumaqq.resource.Colors; import edu.tsinghua.lumaqq.resource.DefaultFace; import edu.tsinghua.lumaqq.resource.Resources; import edu.tsinghua.lumaqq.ui.config.user.UserInfoWindow; import edu.tsinghua.lumaqq.ui.helper.DateTool; import edu.tsinghua.lumaqq.ui.helper.FaceRegistry; import edu.tsinghua.lumaqq.ui.helper.HeadFactory; import edu.tsinghua.lumaqq.ui.jobs.SendNormalIMJob; import edu.tsinghua.lumaqq.widgets.FaceImageAdvisor; import edu.tsinghua.lumaqq.widgets.IImageSelectorAdvisor; import edu.tsinghua.lumaqq.widgets.ImageSelector; import edu.tsinghua.lumaqq.widgets.qstyle.Slat; import edu.tsinghua.lumaqq.widgets.record.FriendRecordProvider; import edu.tsinghua.lumaqq.widgets.record.RecordViewer; import edu.tsinghua.lumaqq.widgets.rich.IRichContent; import edu.tsinghua.lumaqq.widgets.rich.LineStyle; import edu.tsinghua.lumaqq.widgets.rich.RichBox; /** * ???? * * @author luma */ public class SendIMWindow extends Window implements ShellListener, IFaceSelectionListener { /** * <pre> * ? * </pre> * * @author luma */ private class Blink implements Runnable { private boolean flag; private volatile boolean stop; private Image blinkImage; public Blink() { stop = true; } public void setBlinkImage(Image image) { blinkImage = image; stop = false; flag = true; } public void run() { try { if (flag) { getShell().setImage(blinkImage); if (LumaQQ.IS_GTK) ((BorderStyler) getShell().getData(BorderStyler.STYLER)).repaintTitleBar(); } else { getShell().setImage(res.getImage(Resources.icoBlank)); if (LumaQQ.IS_GTK) ((BorderStyler) getShell().getData(BorderStyler.STYLER)).repaintTitleBar(); } flag = !flag; if (!stop) main.getDisplay().timerExec(500, this); else { getShell().setImage(res.getImage(Resources.icoMessage)); if (LumaQQ.IS_GTK) ((BorderStyler) getShell().getData(BorderStyler.STYLER)).repaintTitleBar(); } } catch (SWTException e) { // ??SWTException?dispose? // ?????? } } public void setStop(boolean stop) { this.stop = stop; } public boolean isStop() { return stop; } } private User model; private MainShell main; private Resources res; // ???active private boolean active; private CLabel lblName, lblIp; private RichBox outputBox, inputBox; private RecordViewer viewer; private Menu enterMenu, fileMenu; private Cursor handCursor; private Slat btnMode; private Sash sash; private Blink blinkRunnable; private ViewForm inputForm, outputForm; private String ip, place; // style? private List<LineStyle> styleCache; // ???? private String message; // ?????? private static final LineStyle myStyle = new LineStyle(Colors.MY_HINT_COLOR, null, "", SWT.NORMAL, 9); private static final LineStyle otherStyle = new LineStyle(Colors.BLUE, null, "", SWT.NORMAL, 9); // ?action private Runnable closeAction = new Runnable() { public void run() { getShell().close(); } }; // action private Runnable showRecordAction = new Runnable() { public void run() { showRecord(); } }; // ???action private Runnable sendAction = new Runnable() { public void run() { if (!inputBox.isReadonly()) sendMessage(inputBox.getText()); } }; // ?? private Runnable modeAction = new Runnable() { public void run() { setTalkMode(!model.talkMode); } }; // ? private static boolean IS_GTK; private static boolean IS_MOTIF; private ImageSelector fss; static { String platform = SWT.getPlatform(); IS_GTK = "gtk".equals(platform); IS_MOTIF = "motif".equals(platform); } /** * @param parentShell */ public SendIMWindow(MainShell main, User f) { super(main.getShell()); this.main = main; this.model = f; this.res = Resources.getInstance(); blinkRunnable = new Blink(); blinkRunnable.setBlinkImage(HeadFactory.getSmallHeadByStatus(f)); styleCache = new ArrayList<LineStyle>(); handCursor = main.getDisplay().getSystemCursor(SWT.CURSOR_HAND); resolveIPLocation(f); setBlockOnOpen(false); } /** * ?IP? * * @param f * User */ private void resolveIPLocation(User f) { // IP? if (f.ip == null || Util.isIpZero(f.ip)) { ip = ""; place = unknown_ip; } else { String ipStr = Util.getIpStringFromBytes(f.ip); String port = String.valueOf(f.port); String country = main.getIPSeeker().getCountry(f.ip); String area = main.getIPSeeker().getArea(f.ip); if (area.endsWith("CZ88.NET")) area = ""; if (country != bad_ip_file) place = country + area; else place = bad_ip_file; ip = ipStr + ":" + port; } } public String getIPText() { if (ip.equals("")) return place; else return ip + " - " + place; } /** * * * @param f */ public void refresh(User f) { model = f; setFriendNameLabel(); } /** * ? * * @param fs * @return */ private LineStyle getLineStyle(FontStyle fs) { int fontStyle = 0; if (fs.isBold()) fontStyle |= SWT.BOLD; if (fs.isItalic()) fontStyle |= SWT.ITALIC; if (fontStyle == 0) fontStyle = SWT.NORMAL; return getLineStyle(fs.getFontName(), fontStyle, fs.getFontSize(), fs.getRed(), fs.getGreen(), fs.getBlue()); } /** * ?stylecache??style * * @param style * @return */ private LineStyle getLineStyle(LineStyle ls) { int size = styleCache.size(); for (int i = 0; i < size; i++) { LineStyle style = styleCache.get(i); if (style.equals(ls)) return style; } LineStyle style = (LineStyle) ls.clone(); styleCache.add(style); return style; } /** * ???style * * @param fontName * @param fontStyle * @param fontSize * @param red * @param green * @param blue * @return */ private LineStyle getLineStyle(String fontName, int fontStyle, int fontSize, int red, int green, int blue) { int size = styleCache.size(); for (int i = 0; i < size; i++) { LineStyle style = styleCache.get(i); if (!style.fontName.equals(fontName)) continue; if (style.fontSize != fontSize) continue; if (style.fontStyle != fontStyle) continue; // TODO add underline here if (style.foreground.getRed() != red) continue; if (style.foreground.getGreen() != green) continue; if (style.foreground.getBlue() != blue) continue; return style; } LineStyle style = new LineStyle(new Color(main.getDisplay(), red, green, blue), null, fontName, fontStyle, fontSize); styleCache.add(style); return style; } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#getParentShell() */ @Override protected Shell getParentShell() { return null; } /** * ?Enter?? */ private void initEnterMenu() { enterMenu = new Menu(getShell(), SWT.POP_UP); // Enter?? MenuItem mi = new MenuItem(enterMenu, SWT.RADIO); mi.setText(im_menu_use_enter); mi.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { inputBox.removeUserKeyAction(SWT.MOD1 | SWT.CR); inputBox.setUserKeyAction(SWT.CR, sendAction); inputBox.setKeyBinding(SWT.MOD1 | SWT.CR, RichBox.NEW_LINE); if (model.talkMode) main.getOptionHelper().setUseEnterInTalkMode(true); else main.getOptionHelper().setUseEnterInMessageMode(true); } }); // Ctrl + Enter?? mi = new MenuItem(enterMenu, SWT.RADIO); mi.setText(im_menu_use_ctrl_enter); mi.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { inputBox.removeUserKeyAction(SWT.CR); inputBox.setUserKeyAction(SWT.MOD1 | SWT.CR, sendAction); inputBox.setKeyBinding(SWT.CR, RichBox.NEW_LINE); if (model.talkMode) main.getOptionHelper().setUseEnterInTalkMode(false); else main.getOptionHelper().setUseEnterInMessageMode(false); } }); // ??? enterMenu.addMenuListener(new MenuAdapter() { public void menuShown(MenuEvent e) { refreshEnterMenu(); } }); } /** * ????? */ private void refreshEnterMenu() { boolean b = model.talkMode ? main.getOptionHelper().isUseEnterInTalkMode() : main.getOptionHelper().isUseEnterInMessageMode(); enterMenu.getItem(0).setSelection(b); enterMenu.getItem(1).setSelection(!b); } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ @Override protected void configureShell(Shell newShell) { newShell.setText(NLS.bind(im_title, model.displayName)); newShell.setImage(res.getImage(Resources.icoMessage)); newShell.addControlListener(new ControlAdapter() { public void controlMoved(ControlEvent e) { // ????? Point loc = ((Shell) e.getSource()).getLocation(); model.windowX = loc.x; model.windowY = loc.y; } }); newShell.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { for (LineStyle style : styleCache) { if (style.foreground != null) style.foreground.dispose(); if (style.background != null) style.background.dispose(); } } }); main.getShell().addShellListener(new ShellAdapter() { public void shellClosed(ShellEvent e) { inputBox.dispose(); outputBox.dispose(); } }); if (LumaQQ.IS_GTK) { BorderStyler styler = new BorderStyler(main); styler.setShowMaxButton(true); styler.setHideWhenMinimize(false); styler.decorateShell(newShell); } } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#getShellListener() */ @Override protected ShellListener getShellListener() { return this; } /* * (non-Javadoc) * * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent) */ public void shellActivated(ShellEvent e) { stopBlinkImage(); active = true; } /* * (non-Javadoc) * * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent) */ public void shellDeactivated(ShellEvent e) { active = false; } /* * (non-Javadoc) * * @see org.eclipse.swt.events.ShellAdapter#shellClosed(org.eclipse.swt.events.ShellEvent) */ public void shellClosed(ShellEvent e) { main.getShellRegistry().removeSendIMWindow(model); } /* * (non-Javadoc) * * @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent) */ public void shellDeiconified(ShellEvent e) { } /* * (non-Javadoc) * * @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent) */ public void shellIconified(ShellEvent e) { } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite) */ @Override protected Control createContents(Composite parent) { Composite container = null; if (LumaQQ.IS_GTK) { container = ((BorderStyler) getShell().getData(BorderStyler.STYLER)).getCenter(); } else { parent.setLayout(new FillLayout()); container = (Composite) super.createContents(parent); } GridLayout layout = new GridLayout(); layout.horizontalSpacing = 0; container.setLayout(layout); container.setBackground(Colors.MAINSHELL_BACKGROUND); // ? Composite chatContainer = new Composite(container, SWT.NONE); chatContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); layout = new GridLayout(); layout.marginHeight = layout.marginWidth = 1; layout.horizontalSpacing = layout.verticalSpacing = 0; chatContainer.setLayout(layout); chatContainer.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Composite c = (Composite) e.getSource(); Rectangle rect = c.getClientArea(); rect.width--; rect.height--; e.gc.setForeground(Colors.WIDGET_BORDER); e.gc.drawRectangle(rect); } }); // output form outputForm = new ViewForm(chatContainer, SWT.FLAT); outputForm.setLayoutData(new GridData(GridData.FILL_BOTH)); outputForm.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND); // output form left control Composite left = new Composite(outputForm, SWT.NONE); layout = new GridLayout(2, false); layout.marginHeight = layout.marginWidth = 0; left.setLayout(layout); left.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND); // ?? lblName = new CLabel(left, SWT.LEFT); lblName.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND); setFriendNameLabel(); lblName.setCursor(handCursor); lblName.setForeground(Colors.VIEWFORM_BANNER_TEXT); lblName.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { main.getShellLauncher().openUserInfoWindow(model, UserInfoWindow.READ_ONLY); } }); lblName.addMouseTrackListener(new MouseTrackAdapter() { public void mouseEnter(MouseEvent e) { lblName.setForeground(Colors.VIEWFORM_BANNER_TEXT_HOVER); } public void mouseExit(MouseEvent e) { lblName.setForeground(Colors.VIEWFORM_BANNER_TEXT); } }); // ip lblIp = new CLabel(left, SWT.RIGHT); lblIp.setText(getIPText()); lblIp.setToolTipText(lblIp.getText()); lblIp.setLayoutData(new GridData(GridData.FILL_BOTH)); lblIp.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND); // set left control outputForm.setTopLeft(left); // set content outputBox = new RichBox(outputForm); outputBox.setReadonly(true); outputBox.setBackground(Colors.WHITE); outputForm.setContent(outputBox); sash = new Sash(chatContainer, SWT.HORIZONTAL); sash.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); sash.setBackground(Colors.READONLY_BACKGROUND); sash.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { GridData data = (GridData) inputForm.getLayoutData(); data.heightHint = inputForm.getParent().getClientArea().height - e.y; inputForm.getParent().layout(); } }); inputForm = new ViewForm(chatContainer, SWT.FLAT); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.heightHint = 100; inputForm.setLayoutData(gd); ToolBar tb = new ToolBar(inputForm, SWT.FLAT); tb.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND); // ToolItem ti = new ToolItem(tb, SWT.NONE); ti.setImage(res.getImage(Resources.icoFont)); ti.setToolTipText(tooltip_button_font); ti.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { FontDialog dialog = new FontDialog(getShell()); if (main.getDefaultStyle() != null) dialog.setFontList(main.getDefaultStyle().createFontData()); if (main.getFontColor() != null) dialog.setRGB(main.getFontColor().getRGB()); dialog.open(); FontData[] fontList = dialog.getFontList(); if (fontList == null) return; RGB rgb = dialog.getRGB(); if (main.getFontColor() != null) main.getFontColor().dispose(); main.getDefaultStyle().fontName = fontList[0].getName(); main.getDefaultStyle().fontSize = fontList[0].getHeight(); main.getDefaultStyle().fontStyle = fontList[0].getStyle(); if (rgb != null) { main.setFontColor(new Color(main.getDisplay(), rgb)); main.getDefaultStyle().foreground = main.getFontColor(); } inputBox.setDefaultStyle(main.getDefaultStyle()); } }); // ?? if (IS_GTK || IS_MOTIF) { ToolItem tiColor = new ToolItem(tb, SWT.NONE); tiColor.setImage(res.getImage(Resources.icoColor)); tiColor.setToolTipText(tooltip_button_color); tiColor.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ColorDialog dialog = new ColorDialog(getShell()); if (main.getFontColor() != null) dialog.setRGB(main.getFontColor().getRGB()); dialog.open(); RGB rgb = dialog.getRGB(); if (rgb != null) { if (main.getFontColor() != null) main.getFontColor().dispose(); if (rgb != null) { main.setFontColor(new Color(main.getDisplay(), rgb)); main.getDefaultStyle().foreground = main.getFontColor(); } } inputBox.setDefaultStyle(main.getDefaultStyle()); } }); } // ti = new ToolItem(tb, SWT.NONE); ti.setImage(res.getImage(Resources.icoSmiley)); ti.setToolTipText(tooltip_button_face); ti.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ToolBar toolbar = ((ToolItem) e.widget).getParent(); Rectangle bound = toolbar.getBounds(); openImageSelectionShell(toolbar.getParent().toDisplay(bound.x, bound.y + bound.height)); } }); // ? ti = new ToolItem(tb, SWT.CHECK); ti.setImage(res.getImage(Resources.icoStop)); ti.setToolTipText(tooltip_button_disable_animation); ti.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ToolItem item = (ToolItem) e.widget; outputBox.setForbiddenAnimation(item.getSelection()); inputBox.setForbiddenAnimation(item.getSelection()); item.setToolTipText( item.getSelection() ? tooltip_button_animation : tooltip_button_disable_animation); } }); // input form inputForm.setTopLeft(tb); inputForm.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND); inputBox = new RichBox(inputForm); inputBox.setBackground(Colors.WHITE); inputForm.setContent(inputBox); // Composite buttonContainer = new Composite(container, SWT.NONE); gd = new GridData(GridData.FILL_HORIZONTAL); buttonContainer.setLayoutData(gd); layout = new GridLayout(5, false); layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0; buttonContainer.setLayout(layout); buttonContainer.setBackground(container.getBackground()); Slat btnRecord = new Slat(buttonContainer); btnRecord.setText(button_record_accel); btnRecord.setLayoutData(new GridData()); btnRecord.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { Slat temp = (Slat) e.getSource(); if (e.x > temp.getSize().x || e.y > temp.getSize().y || e.x < 0 || e.y < 0) { return; } showRecord(); } }); btnMode = new Slat(buttonContainer); btnMode.setText(im_button_mode_message); gd = new GridData(); gd.horizontalIndent = 3; btnMode.setLayoutData(gd); btnMode.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { Slat temp = (Slat) e.getSource(); if (e.x > temp.getSize().x || e.y > temp.getSize().y || e.x < 0 || e.y < 0) { return; } setTalkMode(!model.talkMode); } }); Slat btnClose = new Slat(buttonContainer); btnClose.setText(button_close_accel); gd = new GridData(GridData.HORIZONTAL_ALIGN_END); gd.grabExcessHorizontalSpace = true; btnClose.setLayoutData(gd); btnClose.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { Slat temp = (Slat) e.getSource(); if (e.x > temp.getSize().x || e.y > temp.getSize().y || e.x < 0 || e.y < 0) { return; } closeWindow(); } }); final Slat btnSend = new Slat(buttonContainer); btnSend.setText(button_send_accel); gd = new GridData(); gd.horizontalIndent = 3; btnSend.setLayoutData(gd); btnSend.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { Slat temp = (Slat) e.getSource(); if (e.x > temp.getSize().x || e.y > temp.getSize().y || e.x < 0 || e.y < 0) { return; } sendMessage(inputBox.getText()); } }); Slat btnDropDown = new Slat(buttonContainer); btnDropDown.setText(""); gd = new GridData(); gd.horizontalIndent = 1; btnDropDown.setLayoutData(gd); btnDropDown.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { Slat temp = (Slat) e.getSource(); if (e.x > temp.getSize().x || e.y > temp.getSize().y || e.x < 0 || e.y < 0) { return; } // ??? Rectangle bound = btnSend.getBounds(); enterMenu.setLocation(btnSend.getParent().toDisplay(bound.x, bound.y + bound.height)); // ?? enterMenu.setVisible(true); } }); // ??? viewer = new RecordViewer(container, new FriendRecordProvider(model), main); viewer.setFont(res.getDefaultFont()); viewer.setVisible(false); viewer.setRecordManager(main.getRecordManager()); viewer.setBackground(container.getBackground()); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; gd.heightHint = 200; gd.exclude = true; viewer.setLayoutData(gd); // tableitem?? viewer.addSelectionListener(new SelectionAdapter() { public void widgetDefaultSelected(SelectionEvent e) { inputBox.appendText(viewer.getSelectedFullText(), main.getDefaultStyle()); } }); // ??? initEnterMenu(); initFileMenu(); // ?? initKeyAction(); setTalkMode(model.talkMode); return container; } /** * ?? */ private void initKeyAction() { // mod3 -> alt inputBox.setUserKeyAction('C' | SWT.MOD3, closeAction); inputBox.setUserKeyAction('S' | SWT.MOD3, sendAction); inputBox.setUserKeyAction('H' | SWT.MOD3, showRecordAction); inputBox.setUserKeyAction('T' | SWT.MOD3, modeAction); // ???? reinstallSendKey(model.talkMode ? main.getOptionHelper().isUseEnterInTalkMode() : main.getOptionHelper().isUseEnterInMessageMode()); } /** * ??? * * @param useEnter */ private void reinstallSendKey(boolean useEnter) { if (useEnter) { inputBox.removeUserKeyAction(SWT.MOD1 | SWT.CR); inputBox.setUserKeyAction(SWT.CR, sendAction); inputBox.setKeyBinding(SWT.MOD1 | SWT.CR, RichBox.NEW_LINE); } else { inputBox.removeUserKeyAction(SWT.CR); inputBox.setUserKeyAction(SWT.MOD1 | SWT.CR, sendAction); inputBox.setKeyBinding(SWT.CR, RichBox.NEW_LINE); } } /** * ?? */ private void setFriendNameLabel() { FaceRegistry reg = FaceRegistry.getInstance(); if (model.hasCustomHead && reg.hasFace(reg.getMd5ById(model.customHeadId))) lblName.setImage(res.getSmallCustomHead(model.customHeadId, false)); else lblName.setImage(HeadFactory.getSmallHeadByStatus(model)); lblName.setText(model.displayName + " (" + model.qq + ')'); } /** * ?? */ protected void stopBlinkImage() { blinkRunnable.setStop(true); } /** * ? */ public void startBlinkImage() { if (!blinkRunnable.isStop()) return; blinkRunnable.setStop(false); main.getDisplay().timerExec(0, blinkRunnable); } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#getShellStyle() */ @Override protected int getShellStyle() { int onTop = main.getOptionHelper().isIMOnTop() ? SWT.ON_TOP : SWT.NONE; if (LumaQQ.IS_GTK) return SWT.NO_TRIM | SWT.NO_BACKGROUND | onTop; else return SWT.SHELL_TRIM | onTop; } /** * ? */ public void setActive() { getShell().setActive(); } /** * ?? * * @param b */ public void setMinimized(boolean b) { getShell().setMinimized(b); } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#open() */ @Override public int open() { int ret = super.open(); // inputBox.setFocus(); if (main.getDefaultStyle() != null) inputBox.setDefaultStyle(main.getDefaultStyle()); return ret; } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#constrainShellSize() */ @Override protected void constrainShellSize() { if (model.talkMode) getShell().setSize(470, 430); else getShell().setSize(440, 340); Point loc = new Point(50, 50); int x = model.windowX; int y = model.windowY; if (x > 0) loc.x = x; if (y > 0) loc.y = y; getShell().setLocation(loc); } /* * (non-Javadoc) * * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point) */ @Override protected Point getInitialLocation(Point initialSize) { Point loc = new Point(50, 50); int x = model.windowX; int y = model.windowY; if (x > 0) loc.x = x; if (y > 0) loc.y = y; return loc; } /** * ? * * @param f * @param im * @param header */ public void appendMessage(User f, NormalIM im, NormalIMHeader header) { outputBox.appendText( '(' + DefaultFace.escapeFaces(f.displayName) + ") " + DateTool.format(header.sendTime), otherStyle); LineStyle style = getLineStyle(im.fontStyle); outputBox.appendText(im.message, style); } /** * ? * * @param entry * RecordEntry */ private void appendMessage(RecordEntry entry) { outputBox.appendText( '(' + DefaultFace.escapeFaces(main.getMyModel().displayName) + ") " + DateTool.format(entry.time), myStyle); outputBox.appendText(entry.message, getLineStyle(main.getDefaultStyle())); } /** * ??? * * @param hint * @param style */ @SuppressWarnings("unused") public void appendHint(String hint, LineStyle style) { outputBox.appendText(hint, style); } /** * @return true??? */ public boolean isActive() { return active; } /** * ??? * * @param string */ protected void sendMessage(String s) { // ?? if (s.length() == 0) { MessageDialog.openWarning(getShell(), message_box_common_warning_title, message_box_cannot_send_empty_message); return; } // ? if (main.getClient().getUser().isLoggedIn()) { message = s; // ?? RecordEntry key = new RecordEntry(); key.owner = model.qq; key.sender = main.getMyModel().qq; key.senderParent = 0; key.receiver = model.qq; key.time = System.currentTimeMillis(); key.type = IKeyConstants.NORMAL; key.message = message; main.getRecordManager().addRecord(key); // ??? if (model.talkMode) appendMessage(key); if (model.talkMode) inputBox.clear(); else { /* * ?? */ // ?? inputBox.setReadonly(true); inputBox.setBackground(Colors.READONLY_BACKGROUND); // ?? getShell().setMinimized(true); } // TODO ??????QQ???? // ???? main.getIMJobQueue().addJob(new SendNormalIMJob(message, model)); } else { MessageDialog.openWarning(getShell(), message_box_common_warning_title, message_box_please_login_first); } } /** * */ private void showRecord() { GridData gd = (GridData) viewer.getLayoutData(); Shell shell = getShell(); if (gd.exclude) { gd.exclude = false; viewer.refreshRecord(); } else { gd.exclude = true; } if (!shell.getMaximized()) { Point p = shell.getSize(); shell.setSize(p.x, p.y + (gd.exclude ? -205 : 205)); } viewer.setVisible(!gd.exclude); viewer.getParent().layout(); shell.layout(); } /** * ? */ public void closeWindow() { getShell().close(); } /** * ???????? * * @param b * true?? */ public void setTalkMode(boolean b) { if (b) { model.talkMode = true; btnMode.setText(im_button_mode_message); if (main.getOptionHelper().isUseEnterInMessageMode() != main.getOptionHelper().isUseEnterInTalkMode()) reinstallSendKey(main.getOptionHelper().isUseEnterInTalkMode()); sash.setVisible(true); outputForm.setLayoutData(new GridData(GridData.FILL_BOTH)); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.heightHint = 100; inputForm.setLayoutData(gd); gd = (GridData) sash.getLayoutData(); gd.heightHint = SWT.DEFAULT; if (model.talkMode) getShell().setSize(470, viewer.isVisible() ? 630 : 430); else getShell().setSize(440, viewer.isVisible() ? 540 : 340); inputForm.getParent().layout(); } else { outputBox.clear(); model.talkMode = false; btnMode.setText(im_button_mode_talk); if (main.getOptionHelper().isUseEnterInMessageMode() != main.getOptionHelper().isUseEnterInTalkMode()) reinstallSendKey(main.getOptionHelper().isUseEnterInMessageMode()); sash.setVisible(false); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.heightHint = outputForm.getTopLeft().getSize().y + 2; outputForm.setLayoutData(gd); inputForm.setLayoutData(new GridData(GridData.FILL_BOTH)); gd = (GridData) sash.getLayoutData(); gd.heightHint = 0; if (model.talkMode) getShell().setSize(470, viewer.isVisible() ? 630 : 430); else getShell().setSize(440, viewer.isVisible() ? 540 : 340); inputForm.getParent().layout(); } } /** * ???? */ private void initFileMenu() { fileMenu = new Menu(getShell(), SWT.POP_UP); // ? MenuItem mi = new MenuItem(fileMenu, SWT.PUSH); mi.setText(menu_file_none); } /** * */ public void setFocus() { getShell().setFocus(); } /** * @return true?? */ public boolean isTalkMode() { return model.talkMode; } /** * ? */ private void openImageSelectionShell(Point loc) { if (fss != null && !fss.isDisposed()) fss.getShell().close(); fss = new ImageSelector(getShell(), new FaceImageAdvisor(main)); fss.setListener(this); fss.setLocation(loc); fss.open(); } /* * (non-Javadoc) * * @see edu.tsinghua.lumaqq.events.IFaceSelectionListener#faceSelected(edu.tsinghua.lumaqq.ui.IImageProvider, int, int) */ public void faceSelected(IImageSelectorAdvisor provider, int group, int sequence) { if (group == 0) { int index = res.getFaceCode(sequence); if (index != -1) inputBox.insertImage(IRichContent.DEFAULT_FACE_TAG, index); } else { MessageDialog.openInformation(getShell(), message_box_common_info_title, message_box_face_to_user); /* * ??????? */ // FaceUtil util = FaceUtil.getInstance(); // Face face = util.getFace(group - 1, sequence); // if(face == null) // return; // int id = Util.getInt(face.getId(), -1); // if(id == -1) // return; // inputBox.insertImage(IRichContent.CUSTOM_FACE_TAG, id); } } /** * @return the otherStyle */ public static LineStyle getOtherStyle() { return otherStyle; } /** * @return the inputBox */ public RichBox getInputBox() { return inputBox; } }