├── .gitignore
├── README.md
├── api
├── pom.xml
└── src
│ └── main
│ └── java
│ └── iqq
│ └── api
│ ├── annotation
│ └── IMEventHandler.java
│ ├── bean
│ ├── IMAccount.java
│ ├── IMBuddy.java
│ ├── IMBuddyCategory.java
│ ├── IMCategory.java
│ ├── IMDevice.java
│ ├── IMEntity.java
│ ├── IMMsg.java
│ ├── IMRoom.java
│ ├── IMRoomCategory.java
│ ├── IMStatus.java
│ ├── IMUser.java
│ └── content
│ │ ├── IMContentItem.java
│ │ ├── IMContentType.java
│ │ ├── IMFaceItem.java
│ │ ├── IMPictureItem.java
│ │ └── IMTextItem.java
│ ├── common
│ ├── EventBase.java
│ └── Intent.java
│ └── event
│ ├── IMEvent.java
│ ├── IMEventAware.java
│ ├── IMEventDispatcher.java
│ ├── IMEventListener.java
│ ├── IMEventType.java
│ └── args
│ └── LoginRequest.java
├── main
├── config.xml
├── lib
│ ├── jhrome-2.0.jar
│ └── weblaf-1.29.jar
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── iqq
│ │ │ └── app
│ │ │ ├── IMLauncher.java
│ │ │ ├── api
│ │ │ ├── Conn.java
│ │ │ ├── IMRequest.java
│ │ │ ├── IMResponse.java
│ │ │ └── User.java
│ │ │ ├── core
│ │ │ ├── annotation
│ │ │ │ ├── IMModule.java
│ │ │ │ ├── IMQuery.java
│ │ │ │ └── IMService.java
│ │ │ ├── context
│ │ │ │ └── IMContext.java
│ │ │ ├── module
│ │ │ │ ├── AddFriendModule.java
│ │ │ │ ├── LogicModule.java
│ │ │ │ ├── MsgModule.java
│ │ │ │ └── SessionModule.java
│ │ │ ├── query
│ │ │ │ ├── AccountQuery.java
│ │ │ │ ├── BuddyQuery.java
│ │ │ │ ├── GroupQuery.java
│ │ │ │ └── MsgQuery.java
│ │ │ ├── service
│ │ │ │ ├── ConfigService.java
│ │ │ │ ├── EventService.java
│ │ │ │ ├── HttpService.java
│ │ │ │ ├── I18nService.java
│ │ │ │ ├── ResourceService.java
│ │ │ │ ├── SkinService.java
│ │ │ │ ├── TaskService.java
│ │ │ │ ├── TimerService.java
│ │ │ │ └── impl
│ │ │ │ │ ├── EventServiceImpl.java
│ │ │ │ │ ├── HttpServiceImpl.java
│ │ │ │ │ ├── I18nServiceImpl.java
│ │ │ │ │ ├── ResourceServiceImpl.java
│ │ │ │ │ ├── SkinServiceImpl.java
│ │ │ │ │ ├── TaskServiceImpl.java
│ │ │ │ │ └── TimerServiceImpl.java
│ │ │ └── store
│ │ │ │ └── IMDataStore.java
│ │ │ ├── ui
│ │ │ ├── IMContentPane.java
│ │ │ ├── IMDialog.java
│ │ │ ├── IMFrame.java
│ │ │ ├── IMFrameWrap.java
│ │ │ ├── IMPanel.java
│ │ │ ├── IMTree.java
│ │ │ ├── action
│ │ │ │ ├── IMActionHandler.java
│ │ │ │ └── IMActionHandlerProxy.java
│ │ │ ├── border
│ │ │ │ ├── RoundBorder.java
│ │ │ │ ├── ShadeBorder.java
│ │ │ │ └── TabContentPanelBorder.java
│ │ │ ├── component
│ │ │ │ ├── StatusButton.java
│ │ │ │ └── TitleComponent.java
│ │ │ ├── dialog
│ │ │ │ └── TipDialog.java
│ │ │ ├── event
│ │ │ │ ├── UIEvent.java
│ │ │ │ ├── UIEventDispatcher.java
│ │ │ │ ├── UIEventHandler.java
│ │ │ │ ├── UIEventListener.java
│ │ │ │ ├── UIEventType.java
│ │ │ │ └── args
│ │ │ │ │ └── LoginInfoParam.java
│ │ │ ├── frame
│ │ │ │ ├── AddCategoryFrame.java
│ │ │ │ ├── AddFriendFrame.java
│ │ │ │ ├── ChatFrame.java
│ │ │ │ ├── ChooseCategoryFrame.java
│ │ │ │ ├── GetFriendRequestFrame.java
│ │ │ │ ├── LoginFrame.java
│ │ │ │ ├── MainFrame.java
│ │ │ │ ├── SkinFrame.java
│ │ │ │ ├── VerifyFrame.java
│ │ │ │ └── panel
│ │ │ │ │ ├── chat
│ │ │ │ │ ├── BasicPanel.java
│ │ │ │ │ ├── ChatPane.java
│ │ │ │ │ ├── RoomPanel.java
│ │ │ │ │ ├── UserPanel.java
│ │ │ │ │ ├── msg
│ │ │ │ │ │ ├── MsgGroupPanel.java
│ │ │ │ │ │ └── MsgPane.java
│ │ │ │ │ ├── picloader
│ │ │ │ │ │ ├── AbstractPicLoader.java
│ │ │ │ │ │ ├── PicLoadListener.java
│ │ │ │ │ │ ├── PicLoadState.java
│ │ │ │ │ │ ├── PicLoader.java
│ │ │ │ │ │ ├── PicLoaderFactory.java
│ │ │ │ │ │ └── UserPicLoader.java
│ │ │ │ │ └── rich
│ │ │ │ │ │ ├── RichTextPane.java
│ │ │ │ │ │ ├── UIBasicItem.java
│ │ │ │ │ │ ├── UIFaceItem.java
│ │ │ │ │ │ ├── UILinkItem.java
│ │ │ │ │ │ ├── UILoaderPicItem.java
│ │ │ │ │ │ ├── UIRichComponent.java
│ │ │ │ │ │ ├── UIRichItem.java
│ │ │ │ │ │ ├── UISkinPicItem.java
│ │ │ │ │ │ └── UITextItem.java
│ │ │ │ │ ├── login
│ │ │ │ │ ├── LoginPane.java
│ │ │ │ │ └── LoginingPane.java
│ │ │ │ │ └── main
│ │ │ │ │ ├── FooterPanel.java
│ │ │ │ │ ├── HeaderPanel.java
│ │ │ │ │ ├── MainPane.java
│ │ │ │ │ └── MiddlePanel.java
│ │ │ ├── manager
│ │ │ │ ├── ChatManager.java
│ │ │ │ ├── FrameManager.java
│ │ │ │ ├── MainManager.java
│ │ │ │ └── SkinManager.java
│ │ │ ├── renderer
│ │ │ │ ├── BoddyTreeCellRenderer.java
│ │ │ │ ├── CategoryComboxCellRenderer.java
│ │ │ │ ├── RecentTreeCellRenderer.java
│ │ │ │ ├── RoomTreeCellRenderer.java
│ │ │ │ └── node
│ │ │ │ │ ├── BuddyNode.java
│ │ │ │ │ ├── CategoryNode.java
│ │ │ │ │ ├── EntityNode.java
│ │ │ │ │ └── RoomNode.java
│ │ │ └── skin
│ │ │ │ └── Skin.java
│ │ │ └── util
│ │ │ ├── Benchmark.java
│ │ │ ├── StatusUtils.java
│ │ │ ├── UIUtils.java
│ │ │ ├── XmlUtils.java
│ │ │ ├── date
│ │ │ ├── BaseDate.java
│ │ │ ├── Date.java
│ │ │ ├── DateTime.java
│ │ │ ├── DateTimeZone.java
│ │ │ ├── DateUtils.java
│ │ │ └── FriendlyDate.java
│ │ │ └── gson
│ │ │ ├── DateFormatter.java
│ │ │ ├── DateTimeFormatter.java
│ │ │ ├── DateTimeZoneFormatter.java
│ │ │ └── GsonUtils.java
│ └── resources
│ │ ├── META-INF
│ │ └── MANIFEST.MF
│ │ ├── logback.xml
│ │ └── spring-config.xml
│ └── test
│ └── java
│ └── iqq
│ └── app
│ ├── TestIoc.java
│ ├── TestPath.java
│ ├── service
│ ├── TestI18nService.java
│ ├── TestResourceService.java
│ └── TestSkinService.java
│ ├── ui
│ └── TestLogin.java
│ └── util
│ └── TestXml.java
├── pom.xml
├── resources
├── i18n
│ ├── appBundle.properties
│ └── appBundle_zh_CN.properties
├── icons
│ ├── default
│ │ ├── qq_icon.png
│ │ └── qq_icon.svg
│ ├── login
│ │ ├── avatar.jpg
│ │ ├── avatar.png
│ │ ├── avatar2.png
│ │ ├── captcha.jpg
│ │ ├── face.jpg
│ │ ├── group.png
│ │ └── qq_icon.png
│ └── status
│ │ ├── away.png
│ │ ├── callme.png
│ │ ├── hidden.png
│ │ ├── meeting.png
│ │ ├── offline.png
│ │ ├── online.png
│ │ └── silent.png
├── pom.xml
└── screenshots
│ ├── chat-msg.png
│ ├── chat.png
│ ├── main-skin.png
│ ├── main-skin2.png
│ └── main.png
└── skin-default
├── chat
├── bg
│ ├── balloon
│ │ ├── balloon_left_blue.9.png
│ │ ├── balloon_left_green.9.png
│ │ ├── balloon_left_white.9.png
│ │ ├── balloon_right_blue.9.png
│ │ └── balloon_right_grey.9.png
│ └── nav_bg.9.png
└── icons
│ ├── inputbar
│ ├── emoticon.png
│ ├── fileTransfere.png
│ ├── history.png
│ ├── noMessage.png
│ ├── offMessage.png
│ ├── pictures.png
│ ├── screenCapture.png
│ ├── send.png
│ ├── shake.png
│ └── text.png
│ └── setting_icon.png
├── font
└── wqy-microhei.ttc
├── login
├── bg
│ ├── footer_bg.9.png
│ ├── login_bg.9.png
│ └── login_bg2.9.png
└── icons
│ ├── key.png
│ ├── setting.png
│ └── setting_active.png
├── main
├── bg
│ ├── search_bg.9.png
│ └── tab_bg.9.png
└── icons
│ ├── arrow_down.png
│ ├── arrow_left.png
│ ├── search_icon.png
│ ├── tab_boddy.png
│ ├── tab_group.png
│ ├── tab_recent.png
│ └── toolbar
│ ├── add.png
│ ├── mail.png
│ ├── msg_new.png
│ ├── msg_normal.png
│ ├── msgrecode.png
│ ├── qzone.png
│ ├── setting.png
│ └── weibo.png
├── pom.xml
├── skin.xml
├── skin
├── bg
│ ├── 0.9.png
│ ├── 1.9.png
│ ├── 10.9.png
│ ├── 11.9.png
│ ├── 12.9.png
│ ├── 13.9.png
│ ├── 14.9.png
│ ├── 2.9.png
│ ├── 3.9.png
│ ├── 4.9.png
│ ├── 5.9.png
│ ├── 6.9.png
│ ├── 7.9.png
│ ├── 8.9.png
│ └── 9.9.png
└── icons
│ └── skin_icon.png
└── window
├── bg
├── transparent.9.png
└── window_bg.9.png
└── icons
├── close.png
├── close_active.png
├── maximize.png
├── maximize_active.png
├── minimize.png
├── minimize_active.png
├── restore.png
├── restore_active.png
├── setting.png
├── setting_active.png
├── skin.png
├── skin_active.png
├── title_icon.png
├── title_w_icon.png
└── title_w_icon_black.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # iqq working dir
2 | /iqq.log*
3 | /user
4 |
5 | # Build artifacts
6 | artifacts
7 | target
8 | classes
9 |
10 | # IDE & module files
11 | .idea
12 | *.iml
13 | .project
14 | .settings
15 | .classpath
16 | workspace.xml
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 这是一个正在开发的项目,您可以把页面加入书签随时看看我们的进度,也希望您将来能够来看看我们最终的程序。
2 |
3 | 我们目标
4 |
5 | 提供一个基于WebQQ协议开发的库,您可以基于这个库让您的程序集成QQ相关的功能
6 | 提供一个即开即用的桌面QQ客户端,风格可能类似于Mac版QQ
7 |
8 | 项目
9 | IQQ UI: https://github.com/im-qq/iqq.git
10 | IQQ Core: https://github.com/im-qq/webqq-core.git
11 |
12 | 加入开发
13 |
14 | 我们热情的欢迎热衷于开源项目的童鞋加入到开发中来,您可以加入讨论群(164158750)一起讨论项目的方向和进度。
15 |
16 | 百度网盘下载:
17 | http://pan.baidu.com/share/home?uk=3071047022
18 |
19 | 原项目地址:https://code.google.com/p/iqq/
20 |
21 | 新版本截图:
22 | 
23 | 
24 | 
25 | 
26 | 
27 |
--------------------------------------------------------------------------------
/api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | iqq.app
9 | iqq
10 | 3.0.0-SNAPSHOT
11 |
12 |
13 | iqq-api
14 | 3.0.0-SNAPSHOT
15 | iqq api module
16 |
17 |
18 |
19 | org.slf4j
20 | slf4j-api
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/annotation/IMEventHandler.java:
--------------------------------------------------------------------------------
1 | package iqq.api.annotation; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | import iqq.api.event.IMEventType;
19 |
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * 事件处理注解,如果在方法上写上了这个注解,则说明此方法处理对应的消息
27 | *
28 | * Project : iqq
29 | * Author : solosky < solosky772@qq.com >
30 | * Created : 4/13/14
31 | * License : Apache License 2.0
32 | */
33 | @Target(ElementType.METHOD)
34 | @Retention(RetentionPolicy.RUNTIME)
35 | public @interface IMEventHandler {
36 | public IMEventType value();
37 | }
38 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMAccount.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | /**
4 | * Project : iqq-projects
5 | * Author : 承∮诺 < 6208317@qq.com >
6 | * Created : 14-5-4
7 | * License : Apache License 2.0
8 | */
9 | public class IMAccount extends IMUser {
10 | private String account;
11 | private String password;
12 | private boolean isRememberPwd;
13 |
14 | public String getAccount() {
15 | return account;
16 | }
17 |
18 | public void setAccount(String account) {
19 | this.account = account;
20 | }
21 |
22 | public String getPassword() {
23 | return password;
24 | }
25 |
26 | public void setPassword(String password) {
27 | this.password = password;
28 | }
29 |
30 | public boolean isRememberPwd() {
31 | return isRememberPwd;
32 | }
33 |
34 | public void setRememberPwd(boolean isRememberPwd) {
35 | this.isRememberPwd = isRememberPwd;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMBuddy.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: solosky
6 | * Date: 4/19/14
7 | * Time: 8:05 PM
8 | * To change this template use File | Settings | File Templates.
9 | */
10 | public class IMBuddy extends IMUser {
11 | private String remark;
12 |
13 | public String getRemark() {
14 | return remark;
15 | }
16 |
17 | public void setRemark(String remark) {
18 | this.remark = remark;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMBuddyCategory.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | import java.io.Serializable;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | /**
8 | * Project : iqq-projects
9 | * Author : 承∮诺 < 6208317@qq.com >
10 | * Created : 14-5-8
11 | * License : Apache License 2.0
12 | */
13 | public class IMBuddyCategory extends IMCategory implements Serializable {
14 | private List buddyList = new LinkedList();
15 |
16 | public List getBuddyList() {
17 | return buddyList;
18 | }
19 |
20 | public void setBuddyList(List buddyList) {
21 | this.buddyList = buddyList;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMCategory.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Project : iqq-projects
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-5-9
9 | * License : Apache License 2.0
10 | */
11 | public class IMCategory implements Serializable {
12 | private String id;
13 | private String name;
14 |
15 | public String getId() {
16 | return id;
17 | }
18 |
19 | public void setId(String id) {
20 | this.id = id;
21 | }
22 |
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | @Override
32 | public String toString() {
33 | return "IMCategory{" +
34 | "id='" + id + '\'' +
35 | ", name='" + name + '\'' +
36 | '}';
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMDevice.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: solosky
6 | * Date: 4/19/14
7 | * Time: 8:02 PM
8 | * To change this template use File | Settings | File Templates.
9 | */
10 | public enum IMDevice {
11 | PC, WEB, IPAD, IPHONE, ANDROID, OTHER
12 | }
13 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMEntity.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | import java.awt.image.BufferedImage;
4 | import java.io.Serializable;
5 |
6 | /**
7 | * Created with IntelliJ IDEA.
8 | * User: solosky
9 | * Date: 4/19/14
10 | * Time: 7:49 PM
11 | * To change this template use File | Settings | File Templates.
12 | */
13 | public class IMEntity implements Serializable {
14 | private String id;
15 | private String nick;
16 | private String sign;
17 | private String avatar;
18 | private BufferedImage avatarBuffered;
19 |
20 | private Object attachment;
21 |
22 | public String getId() {
23 | return id;
24 | }
25 |
26 | public void setId(String id) {
27 | this.id = id;
28 | }
29 |
30 | public String getNick() {
31 | return nick;
32 | }
33 |
34 | public void setNick(String nick) {
35 | this.nick = nick;
36 | }
37 |
38 | public String getSign() {
39 | return sign;
40 | }
41 |
42 | public void setSign(String sign) {
43 | this.sign = sign;
44 | }
45 |
46 | public String getAvatar() {
47 | return avatar;
48 | }
49 |
50 | public void setAvatar(String avatar) {
51 | this.avatar = avatar;
52 | }
53 |
54 | public BufferedImage getAvatarBuffered() {
55 | return avatarBuffered;
56 | }
57 |
58 | public void setAvatarBuffered(BufferedImage avatarBuffered) {
59 | this.avatarBuffered = avatarBuffered;
60 | }
61 |
62 | public Object getAttachment() {
63 | return attachment;
64 | }
65 |
66 | public void setAttachment(Object attachment) {
67 | this.attachment = attachment;
68 | }
69 |
70 | @Override
71 | public String toString() {
72 | return "IMEntity{" +
73 | "id='" + id + '\'' +
74 | ", nick='" + nick + '\'' +
75 | ", sign='" + sign + '\'' +
76 | ", avatar='" + avatar + '\'' +
77 | ", avatarBuffered=" + avatarBuffered +
78 | '}';
79 | }
80 |
81 | @Override
82 | public boolean equals(Object o) {
83 | if (this == o) return true;
84 | if (o == null || getClass() != o.getClass()) return false;
85 |
86 | IMEntity entity = (IMEntity) o;
87 |
88 | return id.equals(entity.id);
89 |
90 | }
91 |
92 | @Override
93 | public int hashCode() {
94 | return id.hashCode();
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMRoom.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | /**
4 | * Project : iqq-projects
5 | * Author : 承∮诺 < 6208317@qq.com >
6 | * Created : 14-5-9
7 | * License : Apache License 2.0
8 | */
9 | public class IMRoom extends IMEntity {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMRoomCategory.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | import java.util.LinkedList;
4 | import java.util.List;
5 |
6 | /**
7 | * Project : iqq-projects
8 | * Author : 承∮诺 < 6208317@qq.com >
9 | * Created : 14-5-9
10 | * License : Apache License 2.0
11 | */
12 | public class IMRoomCategory extends IMCategory {
13 | private List roomList = new LinkedList<>();
14 |
15 | public List getRoomList() {
16 | return roomList;
17 | }
18 |
19 | public void setRoomList(List roomList) {
20 | this.roomList = roomList;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMStatus.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: solosky
6 | * Date: 4/19/14
7 | * Time: 8:01 PM
8 | * To change this template use File | Settings | File Templates.
9 | *
10 | * 状态 0离线,1在线,2离开,3请勿打扰,4忙碌,5Q我吧,6隐身
11 | */
12 | public enum IMStatus {
13 |
14 | OFFLINE("offline", 0),
15 | ONLINE("online", 1),
16 | AWAY("away", 2),
17 | SILENT("silent", 3),
18 | MEETING("meeting", 4),
19 | CALLME("callme", 5),
20 | HIDDEN("hidden", 6);
21 |
22 | public String name;
23 | public int value;
24 |
25 | IMStatus(String name, int value) {
26 | this.name = name;
27 | this.value = value;
28 | }
29 |
30 | /**
31 | * 原生值转枚举
32 | *
33 | * @param value
34 | * @return
35 | */
36 | public static IMStatus valueOfRaw(int value) {
37 | for (IMStatus status : IMStatus.values()) {
38 | if (status.value == value) {
39 | return status;
40 | }
41 | }
42 | return OFFLINE;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/IMUser.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: solosky
6 | * Date: 4/19/14
7 | * Time: 7:48 PM
8 | * To change this template use File | Settings | File Templates.
9 | */
10 | public class IMUser extends IMEntity {
11 | private IMStatus status;
12 |
13 | public IMStatus getStatus() {
14 | return status;
15 | }
16 |
17 | public void setStatus(IMStatus status) {
18 | this.status = status;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/content/IMContentItem.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean.content;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * 聊天内容接口
7 | *
8 | * Project : iqq-projects
9 | * Author : 承∮诺 < 6208317@qq.com >
10 | * Created : 14-5-15
11 | * License : Apache License 2.0
12 | */
13 | public interface IMContentItem extends Serializable {
14 | public IMContentType getType();
15 | }
16 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/content/IMContentType.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean.content;
2 |
3 | /**
4 | * Project : iqq-projects
5 | * Author : 承∮诺 < 6208317@qq.com >
6 | * Created : 14-5-15
7 | * License : Apache License 2.0
8 | */
9 | public enum IMContentType {
10 | TEXT, FACE, PIC
11 | }
12 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/content/IMFaceItem.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean.content;
2 |
3 | /**
4 | * 聊天表情信息
5 | *
6 | * Project : iqq-projects
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-5-15
9 | * License : Apache License 2.0
10 | */
11 | public class IMFaceItem implements IMContentItem {
12 | private String key;
13 |
14 | @Override
15 | public IMContentType getType() {
16 | return IMContentType.FACE;
17 | }
18 |
19 | public String getKey() {
20 | return key;
21 | }
22 |
23 | public void setKey(String key) {
24 | this.key = key;
25 | }
26 |
27 | @Override
28 | public String toString() {
29 | return "[表情 " + key + "]";
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/content/IMPictureItem.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean.content;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * 聊天图片信息
7 | *
8 | * Project : iqq-projects
9 | * Author : 承∮诺 < 6208317@qq.com >
10 | * Created : 14-5-15
11 | * License : Apache License 2.0
12 | */
13 | public class IMPictureItem implements IMContentItem {
14 | private File file;
15 |
16 | @Override
17 | public IMContentType getType() {
18 | return IMContentType.PIC;
19 | }
20 |
21 | public File getFile() {
22 | return file;
23 | }
24 |
25 | public void setFile(File file) {
26 | this.file = file;
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return "[图片 " + file + "]";
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/bean/content/IMTextItem.java:
--------------------------------------------------------------------------------
1 | package iqq.api.bean.content;
2 |
3 | /**
4 | * 聊天文本信息
5 | *
6 | * Project : iqq-projects
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-5-15
9 | * License : Apache License 2.0
10 | */
11 | public class IMTextItem implements IMContentItem {
12 | private String text;
13 |
14 | public IMTextItem(String text) {
15 | this.text = text;
16 | }
17 |
18 | @Override
19 | public IMContentType getType() {
20 | return IMContentType.TEXT;
21 | }
22 |
23 | public String getText() {
24 | return text;
25 | }
26 |
27 | public void setText(String text) {
28 | this.text = text;
29 | }
30 |
31 | @Override
32 | public String toString() {
33 | return text;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/common/EventBase.java:
--------------------------------------------------------------------------------
1 | package iqq.api.common;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import java.io.Serializable;
20 |
21 | /**
22 | * Project : iqq
23 | * Author : solosky < solosky772@qq.com >
24 | * Created : 6/14/14
25 | * License : Apache License 2.0
26 | */
27 | public class EventBase extends Intent implements Serializable {
28 | protected int eventId;
29 | protected Object target;
30 | protected EventBase relatedEvent;
31 |
32 | public int getEventId() {
33 | return eventId;
34 | }
35 |
36 | public void setEventId(int eventId) {
37 | this.eventId = eventId;
38 | }
39 |
40 | public Object getTarget() {
41 | return target;
42 | }
43 |
44 | public void setTarget(Object target) {
45 | this.target = target;
46 | }
47 |
48 | public EventBase getRelatedEvent() {
49 | return relatedEvent;
50 | }
51 |
52 | public void setRelatedEvent(EventBase relatedEvent) {
53 | this.relatedEvent = relatedEvent;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/common/Intent.java:
--------------------------------------------------------------------------------
1 | package iqq.api.common;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import java.io.Serializable;
20 | import java.util.HashMap;
21 | import java.util.Map;
22 |
23 | /**
24 | * Project : iqq
25 | * Author : solosky < solosky772@qq.com >
26 | * Created : 6/14/14
27 | * License : Apache License 2.0
28 | */
29 | public class Intent implements Serializable {
30 | protected Map dataMap = new HashMap();
31 |
32 | public void putData(String key, Object value) {
33 | this.dataMap.put(key, value);
34 | }
35 |
36 | public boolean hasData(String key) {
37 | return this.dataMap.containsKey(key);
38 | }
39 |
40 | public T getData(String key) {
41 | return (T) this.dataMap.get(key);
42 | }
43 |
44 | public int getInt(String key) {
45 | return getDataEx(key);
46 | }
47 |
48 | public long getLong(String key) {
49 | return getDataEx(key);
50 | }
51 |
52 | public boolean getBoolean(String key) {
53 | return getDataEx(key);
54 | }
55 |
56 | public String getString(String key) {
57 | return getDataEx(key);
58 | }
59 |
60 | private T getDataEx(String key) {
61 | if (hasData(key)) {
62 | return (T) getData(key);
63 | }
64 | return null;
65 | }
66 |
67 | public Map getDataEx() {
68 | return dataMap;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/event/IMEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2
20 | * Package : iqq.action
21 | * File : IMEvent.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-3-10
24 | * License : Apache License 2.0
25 | */
26 | package iqq.api.event;
27 |
28 |
29 | import iqq.api.common.EventBase;
30 |
31 | import java.io.Serializable;
32 |
33 | /**
34 | *
35 | * IM事件,作为所有操作的数据的载体在多个模块中传递消息
36 | *
37 | * @author solosky
38 | *
39 | */
40 | public class IMEvent extends EventBase implements Serializable {
41 | private static final long serialVersionUID = 1L;
42 | private IMEventType type;
43 |
44 | public IMEvent(IMEventType type) {
45 | this.type = type;
46 | }
47 |
48 | public IMEvent() {
49 | }
50 |
51 | public IMEvent(IMEventType type, Object data) {
52 | this.type = type;
53 | this.setTarget(data);
54 | }
55 |
56 |
57 | public IMEventType getType() {
58 | return type;
59 | }
60 |
61 | public void setType(IMEventType type) {
62 | this.type = type;
63 | }
64 |
65 | @Override
66 | public String toString() {
67 | return "IMEvent{" +
68 | "type=" + type +
69 | '}';
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/event/IMEventAware.java:
--------------------------------------------------------------------------------
1 | package iqq.api.event; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : iqq
20 | * Author : solosky < solosky772@qq.com >
21 | * Created : 5/1/14
22 | * License : Apache License 2.0
23 | */
24 | public interface IMEventAware {
25 | public void setIMEventListener(IMEventListener imEventListener);
26 | }
27 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/event/IMEventDispatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.action
21 | * File : IMEventHandlerProxy.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-3-16
24 | * License : Apache License 2.0
25 | */
26 | package iqq.api.event;
27 |
28 | import iqq.api.annotation.IMEventHandler;
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 |
32 | import java.lang.reflect.Method;
33 | import java.util.HashMap;
34 | import java.util.Map;
35 |
36 | /**
37 | * 使用这个类简化事件的注册,分发
38 | * 只需在被代理的类使用@IMEventHandler注解需要处理的事件类型即可
39 | *
40 | * @author solosky
41 | */
42 | public class IMEventDispatcher implements IMEventListener {
43 | private static final Logger LOG = LoggerFactory.getLogger(IMEventDispatcher.class);
44 | private Map methodMap = new HashMap();
45 |
46 | public IMEventDispatcher() {
47 | for (Method m : this.getClass().getDeclaredMethods()) {
48 | if (m.isAnnotationPresent(IMEventHandler.class)) {
49 | IMEventHandler handler = m.getAnnotation(IMEventHandler.class);
50 | this.methodMap.put(handler.value(), m);
51 | if (!m.isAccessible()) {
52 | m.setAccessible(true);
53 | }
54 | }
55 | }
56 | for (Method m : this.getClass().getMethods()) {
57 | if (m.isAnnotationPresent(IMEventHandler.class)) {
58 | IMEventHandler handler = m.getAnnotation(IMEventHandler.class);
59 | this.methodMap.put(handler.value(), m);
60 | if (!m.isAccessible()) {
61 | m.setAccessible(true);
62 | }
63 | }
64 | }
65 | }
66 |
67 | @Override
68 | public void onIMEvent(IMEvent imEvent) {
69 | Method m = methodMap.get(imEvent.getType());
70 | if (m != null) {
71 | try {
72 | m.invoke(this, imEvent);
73 | } catch (Throwable e) {
74 | LOG.warn("invoke IMEventHandler Error!! {}.{}(..)", getClass(), m.getName(), e);
75 | }
76 | } else {
77 | LOG.warn("IMEventHandler Not Found!! imEvent = {}", imEvent);
78 | }
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/event/IMEventListener.java:
--------------------------------------------------------------------------------
1 | package iqq.api.event;
2 |
3 | /**
4 | * IM事件监听器
5 | */
6 | public interface IMEventListener {
7 | /**
8 | * 触发事件回掉
9 | *
10 | * @param imEvent
11 | */
12 | public void onIMEvent(IMEvent imEvent);
13 | }
14 |
--------------------------------------------------------------------------------
/api/src/main/java/iqq/api/event/args/LoginRequest.java:
--------------------------------------------------------------------------------
1 | package iqq.api.event.args;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import iqq.api.bean.IMStatus;
20 |
21 | /**
22 | * Project : iqq
23 | * Author : solosky < solosky772@qq.com >
24 | * Created : 5/1/14
25 | * License : Apache License 2.0
26 | */
27 | public class LoginRequest {
28 | private String username;
29 | private String password;
30 | private IMStatus status;
31 |
32 | public String getUsername() {
33 | return username;
34 | }
35 |
36 | public void setUsername(String username) {
37 | this.username = username;
38 | }
39 |
40 | public String getPassword() {
41 | return password;
42 | }
43 |
44 | public void setPassword(String password) {
45 | this.password = password;
46 | }
47 |
48 | public IMStatus getStatus() {
49 | return status;
50 | }
51 |
52 | public void setStatus(IMStatus status) {
53 | this.status = status;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/main/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | test123
5 |
6 | iqqv3
7 |
8 |
9 |
--------------------------------------------------------------------------------
/main/lib/jhrome-2.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/main/lib/jhrome-2.0.jar
--------------------------------------------------------------------------------
/main/lib/weblaf-1.29.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/main/lib/weblaf-1.29.jar
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/IMLauncher.java:
--------------------------------------------------------------------------------
1 | package iqq.app;
2 |
3 | import iqq.app.core.context.IMContext;
4 | import iqq.app.ui.manager.FrameManager;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
8 | import org.springframework.context.annotation.ComponentScan;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | import javax.swing.*;
12 | import java.io.File;
13 |
14 | /**
15 | * 引导启动类
16 | *
17 | * Project : iqq
18 | * Author : 承∮诺 < 6208317@qq.com >
19 | * Created : 14-4-17
20 | * License : Apache License 2.0
21 | */
22 | @Configuration
23 | @ComponentScan("iqq.app")
24 | public class IMLauncher {
25 | private static final Logger LOG = LoggerFactory.getLogger(IMLauncher.class);
26 |
27 | /**
28 | * 程序入口
29 | *
30 | * @param args
31 | */
32 | public static void main(String[] args) {
33 | SwingUtilities.invokeLater(new Runnable() {
34 | @Override
35 | public void run() {
36 | init();
37 | startup();
38 | }
39 | });
40 | }
41 |
42 | /**
43 | * 启动前配置
44 | */
45 | private static void init() {
46 | // APP路径
47 | String path = System.getProperty("user.dir");
48 | if (new File(path + File.separator + "resources").exists()) {
49 | System.setProperty("app.dir", new File(path).getAbsolutePath());
50 | } else {
51 | // 去掉了最后一个main目录
52 | path = path.substring(0, path.lastIndexOf(File.separator));
53 | System.setProperty("app.dir", new File(path).getAbsolutePath());
54 | }
55 | LOG.info("app.dir = " + System.getProperty("app.dir"));
56 |
57 | // 关闭勾子
58 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
59 | @Override
60 | public void run() {
61 | shutdown();
62 | }
63 | }));
64 | LOG.info("init...");
65 | }
66 |
67 | /**
68 | * 运行程序环境
69 | */
70 | private static void startup() {
71 | IMContext.init(new AnnotationConfigApplicationContext("iqq.app"));
72 |
73 | FrameManager frameManager = IMContext.getBean(FrameManager.class);
74 | frameManager.showLogin();
75 | }
76 |
77 | /**
78 | * 程序关闭
79 | */
80 | private static void shutdown() {
81 | LOG.info("shutdown...");
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/api/Conn.java:
--------------------------------------------------------------------------------
1 | package iqq.app.api;
2 |
3 | /**
4 | * Created by Tony on 4/22/15.
5 | */
6 | public class Conn {
7 | private String key;
8 |
9 | public String getKey() {
10 | return key;
11 | }
12 |
13 | public void setKey(String key) {
14 | this.key = key;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/api/IMRequest.java:
--------------------------------------------------------------------------------
1 | package iqq.app.api;
2 |
3 | import iqq.app.util.gson.GsonUtils;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | /**
9 | * Created by Tony on 4/22/15.
10 | */
11 | public class IMRequest {
12 | private String command;
13 | private Object data;
14 |
15 | public String getCommand() {
16 | return command;
17 | }
18 |
19 | public void setCommand(String command) {
20 | this.command = command;
21 | }
22 |
23 | public Object getData() {
24 | return data;
25 | }
26 |
27 | public void setData(Object data) {
28 | this.data = data;
29 | }
30 |
31 | public void setData(String key, Object value) {
32 | Map map = new HashMap<>();
33 | map.put(key, value);
34 |
35 | data = map;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/api/IMResponse.java:
--------------------------------------------------------------------------------
1 | package iqq.app.api;
2 |
3 | import com.google.gson.JsonObject;
4 | import com.google.gson.JsonParser;
5 | import iqq.app.util.gson.GsonUtils;
6 |
7 | /**
8 | * Created by Tony on 4/22/15.
9 | */
10 | public class IMResponse {
11 | private int status;
12 | private String msg;
13 | private JsonObject data;
14 | private String refer;
15 |
16 | public int getStatus() {
17 | return status;
18 | }
19 |
20 | public void setStatus(int status) {
21 | this.status = status;
22 | }
23 |
24 | public String getMsg() {
25 | return msg;
26 | }
27 |
28 | public void setMsg(String msg) {
29 | this.msg = msg;
30 | }
31 |
32 | public JsonObject getData() {
33 | return data;
34 | }
35 |
36 | public void setData(JsonObject data) {
37 | this.data = data;
38 | }
39 |
40 | public String getRefer() {
41 | return refer;
42 | }
43 |
44 | public void setRefer(String refer) {
45 | this.refer = refer;
46 | }
47 |
48 | public static IMResponse parseJson(String json) {
49 | try {
50 | return GsonUtils.fromJson(json, IMResponse.class);
51 | } catch (Exception e) {
52 | JsonObject object = new JsonParser().parse(json).getAsJsonObject();
53 | IMResponse response = new IMResponse();
54 | response.setStatus(object.get("status").getAsInt());
55 | response.setMsg(object.get("msg").getAsString());
56 | response.setRefer(object.get("refer").getAsString());
57 | return response;
58 | }
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return "ApiData{" +
64 | "status=" + status +
65 | ", msg='" + msg + '\'' +
66 | ", data='" + data + '\'' +
67 | ", refer='" + refer + '\'' +
68 | '}';
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/api/User.java:
--------------------------------------------------------------------------------
1 | package iqq.app.api;
2 |
3 | /**
4 | * Created by Tony on 4/22/15.
5 | */
6 | public class User {
7 | private String id;
8 | private String nick;
9 | private String avatar;
10 | private String status;
11 | private String token;
12 |
13 | public String getId() {
14 | return id;
15 | }
16 |
17 | public void setId(String id) {
18 | this.id = id;
19 | }
20 |
21 | public String getNick() {
22 | return nick;
23 | }
24 |
25 | public void setNick(String nick) {
26 | this.nick = nick;
27 | }
28 |
29 | public String getAvatar() {
30 | return avatar;
31 | }
32 |
33 | public void setAvatar(String avatar) {
34 | this.avatar = avatar;
35 | }
36 |
37 | public String getStatus() {
38 | return status;
39 | }
40 |
41 | public void setStatus(String status) {
42 | this.status = status;
43 | }
44 |
45 | public String getToken() {
46 | return token;
47 | }
48 |
49 | public void setToken(String token) {
50 | this.token = token;
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return "User{" +
56 | "id='" + id + '\'' +
57 | ", nick='" + nick + '\'' +
58 | ", avatar='" + avatar + '\'' +
59 | ", status='" + status + '\'' +
60 | ", token='" + token + '\'' +
61 | '}';
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/annotation/IMModule.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.annotation; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : iqq
20 | * Author : solosky < solosky772@qq.com >
21 | * Created : 4/13/14
22 | * License : Apache License 2.0
23 | */
24 | public @interface IMModule {
25 | }
26 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/annotation/IMQuery.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.annotation; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : iqq
20 | * Author : solosky < solosky772@qq.com >
21 | * Created : 4/13/14
22 | * License : Apache License 2.0
23 | */
24 | public @interface IMQuery {
25 | }
26 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/annotation/IMService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.annotation; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 |
19 | /**
20 | * Project : iqq
21 | * Author : solosky < solosky772@qq.com >
22 | * Created : 4/13/14
23 | * License : Apache License 2.0
24 | */
25 | public @interface IMService {
26 | }
27 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/context/IMContext.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.context;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import org.springframework.context.ApplicationContext;
20 |
21 | /**
22 | * 客户端上下文,所有的创建的对象实例都由上下文管理,也可以从这个类得到任意对象
23 | * 通常来说,不需要直接使用这个类,因为所有的对象都是通过依赖注入的方式自动注入的
24 | * 只有在一些特定的场景,比如某些对象不是由容器管理的情况下才需要使用这个类获得容器中的对象或者创建对象
25 | * Project : iqq
26 | * Author : solosky < solosky772@qq.com >
27 | * Created : 4/13/14
28 | * License : Apache License 2.0
29 | */
30 | public class IMContext {
31 | // /**ioc容器*/
32 | // private Ioc ioc;
33 |
34 | private ApplicationContext applicationContext;
35 |
36 | private static IMContext singleton = new IMContext();
37 |
38 | public static IMContext me() {
39 | return singleton;
40 | }
41 |
42 | public static void init(ApplicationContext ctx) {
43 | me().applicationContext = ctx;
44 | }
45 |
46 | private IMContext() {
47 | // applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");
48 | // applicationContext = new AnnotationConfigApplicationContext("iqq.app");
49 | }
50 |
51 | public static T getBean(Class clazz) {
52 | return singleton.applicationContext.getBean(clazz);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/module/MsgModule.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.module;
2 |
3 | import iqq.api.bean.IMMsg;
4 | import iqq.app.core.query.MsgQuery;
5 | import iqq.app.core.service.EventService;
6 | import iqq.app.ui.event.UIEvent;
7 | import iqq.app.ui.event.UIEventDispatcher;
8 | import iqq.app.ui.event.UIEventHandler;
9 | import iqq.app.ui.event.UIEventType;
10 | import org.springframework.stereotype.Service;
11 |
12 | import javax.annotation.PostConstruct;
13 | import javax.annotation.Resource;
14 | import java.util.HashMap;
15 | import java.util.LinkedList;
16 | import java.util.List;
17 | import java.util.Map;
18 |
19 | /**
20 | * 消息处理模块
21 | *
22 | * Created by Tony on 5/3/15.
23 | */
24 | @Service
25 | public class MsgModule implements MsgQuery {
26 | @Resource
27 | private EventService eventService;
28 | private Map> msgsMap = new HashMap<>();
29 |
30 | @PostConstruct
31 | public void init() {
32 |
33 | UIEventDispatcher uiEventDispatcher = new UIEventDispatcher(this);
34 | eventService.register(uiEventDispatcher.getEventTypes(), uiEventDispatcher);
35 | }
36 |
37 | @UIEventHandler(UIEventType.RECV_RAW_MSG)
38 | private void onMsgRecvEvent(UIEvent uiEvent) {
39 | IMMsg msg = (IMMsg) uiEvent.getTarget();
40 | String id = msg.getSender().getId();
41 | if (!msgsMap.containsKey(id)) {
42 | msgsMap.put(id, new LinkedList<>());
43 | }
44 | msgsMap.get(id).add(msg);
45 | }
46 |
47 | @UIEventHandler(UIEventType.SEND_MSG_REQUEST)
48 | private void onSendMsgEvent(UIEvent uiEvent) {
49 | IMMsg msg = (IMMsg) uiEvent.getTarget();
50 | String id = msg.getOwner().getId();
51 | if (!msgsMap.containsKey(id)) {
52 | msgsMap.put(id, new LinkedList<>());
53 | }
54 | msgsMap.get(id).add(msg);
55 | }
56 |
57 | @Override
58 | public List getMsgs(String uid) {
59 | if (!msgsMap.containsKey(uid)) {
60 | msgsMap.put(uid, new LinkedList<>());
61 | }
62 | return msgsMap.get(uid);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/module/SessionModule.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.module;
2 |
3 | import iqq.api.bean.IMEntity;
4 | import iqq.api.bean.IMMsg;
5 | import iqq.api.bean.IMUser;
6 | import iqq.app.core.service.EventService;
7 | import iqq.app.ui.event.UIEvent;
8 | import iqq.app.ui.event.UIEventDispatcher;
9 | import iqq.app.ui.event.UIEventHandler;
10 | import iqq.app.ui.event.UIEventType;
11 | import org.springframework.stereotype.Service;
12 |
13 | import javax.annotation.PostConstruct;
14 | import javax.annotation.Resource;
15 | import java.util.*;
16 |
17 | /**
18 | * 会话模块
19 | *
20 | * Created by Tony on 5/3/15.
21 | */
22 | @Service
23 | public class SessionModule {
24 |
25 | @Resource
26 | private EventService eventService;
27 | private Set entities = new HashSet<>();
28 |
29 | @PostConstruct
30 | public void init() {
31 |
32 | UIEventDispatcher uiEventDispatcher = new UIEventDispatcher(this);
33 | eventService.register(uiEventDispatcher.getEventTypes(), uiEventDispatcher);
34 | }
35 |
36 | @UIEventHandler(UIEventType.SHOW_CHAT)
37 | private void onShowChatEvent(UIEvent uiEvent) {
38 | IMEntity entity = (IMEntity) uiEvent.getTarget();
39 | entities.add(entity);
40 |
41 | eventService.broadcast(new UIEvent(UIEventType.FLASH_USER_STOP, entity));
42 | }
43 |
44 | @UIEventHandler(UIEventType.CLOSE_CHAT)
45 | private void onCloseChatEvent(UIEvent uiEvent) {
46 | IMEntity entity = (IMEntity) uiEvent.getTarget();
47 | entities.remove(entity);
48 | }
49 |
50 | @UIEventHandler(UIEventType.RECV_RAW_MSG)
51 | private void onMsgRecvEvent(UIEvent uiEvent) {
52 | IMMsg msg = (IMMsg) uiEvent.getTarget();
53 |
54 | IMEntity sender = msg.getSender();
55 | if (!entities.contains(sender)) {
56 | eventService.broadcast(new UIEvent(UIEventType.FLASH_USER_START, sender));
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/query/AccountQuery.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.query;
2 |
3 | import iqq.api.bean.IMAccount;
4 |
5 | /**
6 | * Created by Tony on 4/7/15.
7 | */
8 | public interface AccountQuery {
9 |
10 | public IMAccount getOwner();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/query/BuddyQuery.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.query;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import iqq.api.bean.IMBuddy;
20 |
21 | import java.util.List;
22 |
23 | /**
24 | * 好友列表查询接口
25 | * Project : iqq
26 | * Author : solosky < solosky772@qq.com >
27 | * Created : 4/13/14
28 | * License : Apache License 2.0
29 | */
30 | public interface BuddyQuery {
31 | public IMBuddy findById(String id);
32 |
33 | public List findAll();
34 | }
35 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/query/GroupQuery.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.query; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * 群和讨论组查询
20 | * Project : iqq
21 | * Author : solosky < solosky772@qq.com >
22 | * Created : 4/13/14
23 | * License : Apache License 2.0
24 | */
25 | public interface GroupQuery {
26 | }
27 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/query/MsgQuery.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.query;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import iqq.api.bean.IMMsg;
20 |
21 | import java.util.List;
22 |
23 | /**
24 | * QQ消息查询
25 | * Project : iqq
26 | * Author : solosky < solosky772@qq.com >
27 | * Created : 4/13/14
28 | * License : Apache License 2.0
29 | */
30 | public interface MsgQuery {
31 | List getMsgs(String uid);
32 | }
33 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/ConfigService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | /**
20 | * Project : iqq
21 | * Author : solosky < solosky772@qq.com >
22 | * Created : 4/13/14
23 | * License : Apache License 2.0
24 | */
25 | public interface ConfigService {
26 | }
27 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/EventService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import iqq.app.ui.event.UIEvent;
20 | import iqq.app.ui.event.UIEventListener;
21 | import iqq.app.ui.event.UIEventType;
22 |
23 | /**
24 | * Project : iqq
25 | * Author : solosky < solosky772@qq.com >
26 | * Created : 5/3/14
27 | * License : Apache License 2.0
28 | */
29 | public interface EventService {
30 |
31 | /**
32 | * 注册自己感兴趣的事件到事件中心
33 | * 如果该模块被卸载或者禁用了,请务必取消注册
34 | *
35 | * @param intrestedEvents 感兴趣的事件ID,可以是多个
36 | * @param listener 监听器
37 | */
38 | public void register(UIEventType[] intrestedEvents, UIEventListener listener);
39 |
40 | /**
41 | * 只注销已经注册特定的事件监听器
42 | *
43 | * @param intrestedEvents
44 | * @param listener
45 | */
46 | public void unregister(UIEventType[] intrestedEvents, UIEventListener listener);
47 |
48 | /**
49 | * 注销和指定监听器所有感兴趣的事件
50 | *
51 | * @param listener
52 | */
53 | public void unregister(UIEventListener listener);
54 |
55 |
56 | /**
57 | * 广播一个事件,所有对这个感兴趣的监听器都会被调用
58 | *
59 | * @param event
60 | */
61 | public void broadcast(UIEvent event);
62 | }
63 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/HttpService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service;
2 |
3 | import java.util.Map;
4 |
5 | /**
6 | * Created by Tony on 4/21/15.
7 | */
8 | public interface HttpService {
9 |
10 | void doGet(String url, StringCallback callback);
11 |
12 | void doPost(String url, Map params, StringCallback callback);
13 |
14 | interface StringCallback {
15 | void onSuccess(String content);
16 |
17 | void onFailure(int statusCode, String content);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/I18nService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | import iqq.app.core.annotation.IMService;
19 |
20 | import java.util.Locale;
21 |
22 | /**
23 | * Project : iqq
24 | * Author : solosky < solosky772@qq.com >
25 | * Created : 4/13/14
26 | * License : Apache License 2.0
27 | */
28 | @IMService
29 | public interface I18nService {
30 |
31 | /**
32 | * 根据设置的语言获取国际化资源
33 | *
34 | * @param messageKey
35 | * @return
36 | */
37 | public String getMessage(String messageKey);
38 |
39 | /**
40 | * 根据设置的语言获取国际化资源,支持格式化串
41 | *
42 | * @param messageKey
43 | * @param params
44 | * @return
45 | */
46 | public String getMessage(String messageKey, Object... params);
47 |
48 | /**
49 | * 根据固定语言获取国际化资源
50 | *
51 | * @param messageKey
52 | * @param locale
53 | * @return
54 | */
55 | public String getMessage(String messageKey, Locale locale);
56 |
57 | /**
58 | * 根据固定语言获取国际化资源,支持格式化串
59 | *
60 | * @param messageKey
61 | * @param locale
62 | * @param params
63 | * @return
64 | */
65 | public String getMessage(String messageKey, Locale locale, Object... params);
66 |
67 | /**
68 | * 获取当前语言
69 | *
70 | * @return
71 | */
72 | public Locale getCurrentLocale();
73 |
74 | /**
75 | * 获取国际化资源文件目录
76 | *
77 | * @return
78 | */
79 | public String getI18nDirectory();
80 | }
81 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/ResourceService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import javax.swing.*;
20 | import java.io.File;
21 |
22 | /**
23 | * 资源文件获取服务
24 | *
25 | * Project : iqq
26 | * Author : solosky < solosky772@qq.com >
27 | * Created : 4/13/14
28 | * License : Apache License 2.0
29 | */
30 | public interface ResourceService {
31 | /**
32 | * 获取绝对资源目录
33 | *
34 | * @return
35 | */
36 | public String getResourcePath();
37 |
38 | /**
39 | * 获取资源文件
40 | *
41 | * @param filename
42 | * @return
43 | */
44 | public File getFile(String filename);
45 |
46 |
47 | /**
48 | * 获取资源文件图片
49 | *
50 | * @param filename
51 | * @return
52 | */
53 | public ImageIcon getIcon(String filename);
54 |
55 |
56 | /**
57 | * 获取资源文件图片,调整为固定大小
58 | *
59 | * @param filename
60 | * @param width
61 | * @param height
62 | * @return
63 | */
64 | public ImageIcon getIcon(String filename, int width, int height);
65 |
66 |
67 | /**
68 | * 获取用户目录
69 | *
70 | * @return
71 | */
72 | public String getUserPath();
73 |
74 | /**
75 | * 获取用户目录下面的文件
76 | *
77 | * @param filename
78 | * @return
79 | */
80 | public File getUserFile(String filename);
81 |
82 |
83 | /**
84 | * 获取资源文件图片
85 | *
86 | * @param filename
87 | * @return
88 | */
89 | public ImageIcon getUserIcon(String filename);
90 |
91 |
92 | /**
93 | * 获取资源文件图片,调整为固定大小
94 | *
95 | * @param filename
96 | * @param width
97 | * @param height
98 | * @return
99 | */
100 | public ImageIcon getUserIcon(String filename, int width, int height);
101 |
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/SkinService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service;
2 |
3 | import com.alee.extended.painter.Painter;
4 |
5 | import javax.swing.*;
6 | import java.awt.*;
7 |
8 | /**
9 | * Project : iqq-projects
10 | * Author : 承∮诺 < 6208317@qq.com >
11 | * Created : 14-4-15
12 | * License : Apache License 2.0
13 | */
14 | public interface SkinService {
15 |
16 | /**
17 | * 获取颜色
18 | *
19 | * @return
20 | */
21 | public Color getColorByKey(String key);
22 |
23 | /**
24 | * 获取图标
25 | *
26 | * @param key
27 | * @return
28 | */
29 | public ImageIcon getIconByKey(String key);
30 |
31 | /**
32 | * 获取资源文件图片,调整为固定大小
33 | *
34 | * @param filename
35 | * @param width
36 | * @param height
37 | * @return
38 | */
39 | public ImageIcon getIconByKey(String key, int width, int height);
40 |
41 | /**
42 | * 获取点9图的Painter
43 | *
44 | * @param key
45 | * @return
46 | */
47 | public Painter getPainterByKey(String key);
48 |
49 | /**
50 | * 获取默认的皮肤配置文件
51 | *
52 | * @return
53 | */
54 | public String getDefaultConfig();
55 |
56 | /**
57 | * 获取自定义皮肤目录
58 | *
59 | * @return
60 | */
61 | public String getDirectory();
62 |
63 | /**
64 | * 设置自定义皮肤目录
65 | *
66 | * @param path
67 | */
68 | public void setDirectory(String path);
69 |
70 | /**
71 | * 是否启用了自定义皮肤
72 | *
73 | * @return
74 | */
75 | public boolean isEnabledCustom();
76 |
77 | /**
78 | * 设置启用自定义皮肤
79 | *
80 | * @param enable
81 | */
82 | public void setEnableCustom(boolean enable);
83 |
84 | /**
85 | * 设置默认字体
86 | *
87 | * @param vFont
88 | */
89 | public void setDefaultFont(Font vFont);
90 | }
91 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/TaskService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.service
21 | * File : IMTaskService.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-3-25
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.core.service;
27 |
28 |
29 | /**
30 | *
31 | * 异步任务执行
32 | * 可以把一些可能比较耗时的任务单独放在另外一个线程处理,如IO操作等
33 | *
34 | * @author solosky
35 | *
36 | */
37 | public interface TaskService {
38 | public void submit(Runnable runnable);
39 |
40 | public void submit(Object target, String method, Object... args);
41 | }
42 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/TimerService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service;
2 |
3 | /**
4 | * Created by Tony on 5/3/15.
5 | */
6 | public interface TimerService {
7 |
8 | void setInterval(Runnable runnable, long interval);
9 |
10 | void setTimeout(Runnable runnable, long delay);
11 |
12 | void killTimer(Runnable runnable);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/impl/HttpServiceImpl.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service.impl;
2 |
3 | import iqq.app.core.service.HttpService;
4 | import org.apache.http.HttpResponse;
5 | import org.apache.http.HttpStatus;
6 | import org.apache.http.NameValuePair;
7 | import org.apache.http.client.HttpClient;
8 | import org.apache.http.client.entity.UrlEncodedFormEntity;
9 | import org.apache.http.client.methods.HttpGet;
10 | import org.apache.http.client.methods.HttpPost;
11 | import org.apache.http.impl.client.DefaultHttpClient;
12 | import org.apache.http.message.BasicNameValuePair;
13 | import org.apache.http.util.EntityUtils;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 | import org.springframework.stereotype.Service;
17 |
18 | import java.io.IOException;
19 | import java.io.UnsupportedEncodingException;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 | import java.util.Map;
23 | import java.util.concurrent.ExecutorService;
24 | import java.util.concurrent.Executors;
25 |
26 | /**
27 | * Created by Tony on 4/21/15.
28 | */
29 | @Service
30 | public class HttpServiceImpl implements HttpService {
31 | private Logger logger = LoggerFactory.getLogger(HttpServiceImpl.class);
32 |
33 | private ExecutorService poolExecutor = Executors.newCachedThreadPool();
34 | private HttpClient client = new DefaultHttpClient();
35 |
36 | @Override
37 | public void doGet(String url, StringCallback callback) {
38 | logger.debug("doGet " + url);
39 | poolExecutor.submit(new Runnable() {
40 | @Override
41 | public void run() {
42 | HttpGet request = new HttpGet(url);
43 | try {
44 | HttpResponse response = client.execute(request);
45 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
46 | String content = EntityUtils.toString(response.getEntity());
47 | callback.onSuccess(content);
48 | } else {
49 | callback.onFailure(response.getStatusLine().getStatusCode(), "");
50 | }
51 | } catch (IOException e) {
52 | e.printStackTrace();
53 | }
54 | }
55 | });
56 | }
57 |
58 | @Override
59 | public void doPost(String url, Map params, StringCallback callback) {
60 | logger.debug("doPost " + url + " " + params);
61 |
62 | poolExecutor.submit(new Runnable() {
63 | @Override
64 | public void run() {
65 | HttpPost request = new HttpPost(url);
66 | List formparams = new ArrayList<>();
67 | for (String key : params.keySet()) {
68 | formparams.add(new BasicNameValuePair(key, params.get(key)));
69 | }
70 | try {
71 | request.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
72 | } catch (UnsupportedEncodingException e) {
73 | e.printStackTrace();
74 | }
75 | try {
76 | HttpResponse response = client.execute(request);
77 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
78 | String content = EntityUtils.toString(response.getEntity());
79 | callback.onSuccess(content);
80 | } else {
81 | callback.onFailure(response.getStatusLine().getStatusCode(), "");
82 | }
83 | } catch (IOException e) {
84 | e.printStackTrace();
85 | }
86 | }
87 | });
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/impl/ResourceServiceImpl.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service.impl;
2 |
3 | import iqq.app.core.service.ResourceService;
4 | import org.springframework.stereotype.Service;
5 |
6 | import javax.swing.*;
7 | import java.io.File;
8 |
9 | /**
10 | * 资源文件获取服务
11 | *
12 | * #还没有加入缓存优化
13 | *
14 | * Project : iqq
15 | * Author : 承∮诺 < 6208317@qq.com >
16 | * Created : 14-4-17
17 | * License : Apache License 2.0
18 | */
19 | @Service
20 | public class ResourceServiceImpl implements ResourceService {
21 | /**
22 | * 资源文件目录
23 | */
24 | public static final String RESOURCES_DIR = System.getProperty("app.dir", System.getProperty("user.dir")) + File.separator + "resources" + File.separator;
25 |
26 | public static final String USER_DIR = "user" + File.separator;
27 |
28 | /**
29 | * 获取绝对资源目录
30 | *
31 | * @return
32 | */
33 | @Override
34 | public String getResourcePath() {
35 | return RESOURCES_DIR;
36 | }
37 |
38 | /**
39 | * 获取资源文件
40 | *
41 | * @param filename
42 | * @return
43 | */
44 | @Override
45 | public File getFile(String filename) {
46 | return new File(RESOURCES_DIR + filename);
47 | }
48 |
49 | /**
50 | * 获取资源文件图片
51 | *
52 | * @param filename
53 | * @return
54 | */
55 | @Override
56 | public ImageIcon getIcon(String filename) {
57 | return new ImageIcon(getFile(filename).getAbsolutePath());
58 | }
59 |
60 | /**
61 | * 获取资源文件图片,调整为固定大小
62 | *
63 | * @param filename
64 | * @param width
65 | * @param height
66 | * @return
67 | */
68 | @Override
69 | public ImageIcon getIcon(String filename, int width, int height) {
70 | return new ImageIcon(getIcon(filename).getImage().getScaledInstance(width, height, 100));
71 | }
72 |
73 | /**
74 | * 获取用户目录
75 | *
76 | * @return
77 | */
78 | @Override
79 | public String getUserPath() {
80 | return getResourcePath() + USER_DIR;
81 | }
82 |
83 | /**
84 | * 获取用户目录下面的文件
85 | *
86 | * @param filename
87 | * @return
88 | */
89 | @Override
90 | public File getUserFile(String filename) {
91 | return new File(RESOURCES_DIR + filename);
92 | }
93 |
94 | /**
95 | * 获取资源文件图片
96 | *
97 | * @param filename
98 | * @return
99 | */
100 | @Override
101 | public ImageIcon getUserIcon(String filename) {
102 | return new ImageIcon(getUserFile(filename).getAbsolutePath());
103 | }
104 |
105 | /**
106 | * 获取资源文件图片,调整为固定大小
107 | *
108 | * @param filename
109 | * @param width
110 | * @param height
111 | * @return
112 | */
113 | @Override
114 | public ImageIcon getUserIcon(String filename, int width, int height) {
115 | return new ImageIcon(getUserIcon(filename).getImage().getScaledInstance(width, height, 100));
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/impl/TaskServiceImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.service.impl
21 | * File : IMTaskServiceImpl.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-3-25
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.core.service.impl;
27 |
28 |
29 | import iqq.app.core.service.TaskService;
30 | import org.slf4j.Logger;
31 | import org.slf4j.LoggerFactory;
32 | import org.springframework.stereotype.Service;
33 |
34 | import java.lang.reflect.Method;
35 | import java.util.concurrent.ExecutorService;
36 | import java.util.concurrent.Executors;
37 |
38 | /**
39 | * @author solosky
40 | */
41 | @Service
42 | public class TaskServiceImpl implements TaskService {
43 | private final Logger logger = LoggerFactory.getLogger(TaskServiceImpl.class);
44 | private ExecutorService threads = Executors.newFixedThreadPool(2);
45 |
46 | @Override
47 | public void submit(Runnable runnable) {
48 | threads.submit(runnable);
49 | }
50 |
51 | @Override
52 | public void submit(final Object target, final String method, final Object... args) {
53 | threads.submit(new Runnable() {
54 | public void run() {
55 | for (Method m : target.getClass().getDeclaredMethods()) {
56 | if (m.getName().equals(method)) {
57 | try {
58 | if (!m.isAccessible()) {
59 | m.setAccessible(true);
60 | }
61 | m.invoke(target, args);
62 | return;
63 | } catch (Throwable e) {
64 | logger.warn("invoke method error!!", e);
65 | }
66 | }
67 | }
68 | }
69 | });
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/service/impl/TimerServiceImpl.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.service.impl;
2 |
3 | import iqq.app.core.service.TimerService;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.springframework.beans.factory.InitializingBean;
7 | import org.springframework.stereotype.Service;
8 |
9 | import javax.swing.*;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Timer;
13 | import java.util.TimerTask;
14 |
15 | /**
16 | * 默认定时器实现
17 | *
18 | * Created by Tony on 5/3/15.
19 | */
20 | @Service
21 | public class TimerServiceImpl implements TimerService, InitializingBean {
22 |
23 | private static Logger LOG = LoggerFactory.getLogger(TimerServiceImpl.class);
24 | private Timer timer;
25 | private Map map;
26 |
27 | @Override
28 | public void afterPropertiesSet() throws Exception {
29 | timer = new Timer();
30 | map = new HashMap<>();
31 | }
32 |
33 | @Override
34 | public void setInterval(Runnable runnable, long interval) {
35 | TimerAdapter adapter = new TimerAdapter(runnable);
36 | map.put(runnable, adapter);
37 | timer.schedule(adapter, interval, interval);
38 | }
39 |
40 | @Override
41 | public void setTimeout(Runnable runnable, long delay) {
42 | TimerAdapter adapter = new TimerAdapter(runnable);
43 | map.put(runnable, adapter);
44 | timer.schedule(adapter, delay);
45 | }
46 |
47 | @Override
48 | public void killTimer(Runnable runnable) {
49 | if (map.containsKey(runnable)) {
50 | TimerAdapter adapter = map.get(runnable);
51 | adapter.cancel();
52 | timer.purge();
53 | }
54 | }
55 |
56 | private static class TimerAdapter extends TimerTask {
57 | private Runnable runnable;
58 |
59 | public TimerAdapter(Runnable runnable) {
60 | this.runnable = runnable;
61 | }
62 |
63 | @Override
64 | public void run() {
65 | SwingUtilities.invokeLater(new Runnable() {
66 | @Override
67 | public void run() {
68 | try {
69 | runnable.run();
70 | } catch (Throwable e) {
71 | LOG.warn("TimerAdapter run timer error!", e);
72 | }
73 | }
74 | });
75 | }
76 |
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/core/store/IMDataStore.java:
--------------------------------------------------------------------------------
1 | package iqq.app.core.store; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | import iqq.api.bean.IMBuddy;
19 |
20 | /**
21 | * Project : iqq
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 5/3/14
24 | * License : Apache License 2.0
25 | */
26 | public interface IMDataStore {
27 | public void addBuddy(IMBuddy buddy);
28 |
29 | public void removeBuddyById(long id);
30 | }
31 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/IMContentPane.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui;
2 |
3 | /**
4 | * Project : iqq-projects
5 | * Author : 承∮诺 < 6208317@qq.com >
6 | * Created : 14-5-11
7 | * License : Apache License 2.0
8 | */
9 | public class IMContentPane extends IMPanel {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/IMFrameWrap.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui;
2 |
3 | import com.alee.extended.painter.NinePatchIconPainter;
4 | import com.alee.extended.painter.Painter;
5 | import com.alee.laf.panel.WebPanel;
6 | import com.alee.utils.NinePatchUtils;
7 | import com.alee.utils.SystemUtils;
8 | import iqq.app.core.service.SkinService;
9 | import iqq.app.ui.skin.Skin;
10 |
11 | /**
12 | * 窗口阴影背景
13 | *
14 | * Project : iqq-projects
15 | * Author : 承∮诺 < 6208317@qq.com >
16 | * Created : 14-5-5
17 | * License : Apache License 2.0
18 | */
19 | public class IMFrameWrap extends WebPanel implements Skin {
20 |
21 | @Override
22 | public void installSkin(SkinService skinService) {
23 | // 背景只带了阴影,就只是一个底而已
24 | // mac下忽略背影
25 | if (!SystemUtils.isMac()) {
26 | Painter painter = new NinePatchIconPainter(NinePatchUtils.getShadeIcon(20, 1, 0.75f));
27 | setPainter(painter);
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/IMPanel.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui;
2 |
3 | import com.alee.laf.panel.WebPanel;
4 | import iqq.app.core.service.SkinService;
5 | import iqq.app.ui.skin.Skin;
6 |
7 | /**
8 | * 面板封装类
9 | *
10 | * Project : iqq-projects
11 | * Author : 承∮诺 < 6208317@qq.com >
12 | * Created : 14-5-7
13 | * License : Apache License 2.0
14 | */
15 | public class IMPanel extends WebPanel implements Skin {
16 | public IMPanel() {
17 | this.setOpaque(false);
18 | }
19 |
20 | @Override
21 | public void installSkin(SkinService skinService) {
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/IMTree.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui;
2 |
3 | import com.alee.extended.tree.WebAsyncTree;
4 | import com.alee.laf.tree.WebTreeUI;
5 | import iqq.app.core.service.SkinService;
6 | import iqq.app.ui.skin.Skin;
7 |
8 | import javax.swing.*;
9 | import javax.swing.tree.TreeSelectionModel;
10 | import java.awt.*;
11 | import java.awt.geom.RoundRectangle2D;
12 |
13 | /**
14 | * 树组件,继承于weblaf的异步加载树组件
15 | *
16 | * Project : iqq-projects
17 | * Author : 承∮诺 < 6208317@qq.com >
18 | * Created : 14-5-8
19 | * License : Apache License 2.0
20 | */
21 | public class IMTree extends WebAsyncTree implements Skin {
22 |
23 | public IMTree() {
24 | this.setPaintLines(false);
25 | this.setOpaque(false);
26 | this.setRootVisible(false);
27 | this.setShowsRootHandles(false);
28 | this.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
29 | this.setUI(new IMTreeUI());
30 | }
31 |
32 | @Override
33 | public void installSkin(SkinService skinService) {
34 |
35 | }
36 |
37 | class IMTreeUI extends WebTreeUI {
38 | public Color selectedBg = new Color(240, 220, 147);
39 | public Color rolloverBg = new Color(178, 212, 243);
40 |
41 | /**
42 | * 选中时画背景
43 | *
44 | * @param g2d
45 | */
46 | @Override
47 | protected void paintSelection(Graphics2D g2d) {
48 | if (tree.getSelectionCount() > 0) {
49 | // Draw final selections
50 | final java.util.List selections = getSelectionRects();
51 | for (final Rectangle rect : selections) {
52 | g2d.setPaint(selectedBg);
53 | g2d.fill(new RoundRectangle2D.Double(rect.x + selectionShadeWidth, rect.y + selectionShadeWidth,
54 | rect.width - selectionShadeWidth * 2 - 1, rect.height - selectionShadeWidth * 2 - 1, 0,
55 | 0));
56 | }
57 | }
58 | }
59 |
60 | /**
61 | * 鼠标经过画背景
62 | *
63 | * @param g2d
64 | */
65 | @Override
66 | protected void paintRolloverNodeHighlight(Graphics2D g2d) {
67 | if (tree.isEnabled() && highlightRolloverNode && rolloverRow != -1 && !tree.isRowSelected(rolloverRow)) {
68 | final Rectangle rect = isFullLineSelection() ? getFullRowBounds(rolloverRow) : tree.getRowBounds(rolloverRow);
69 | if (rect != null) {
70 | //final Composite old = LafUtils.setupAlphaComposite ( g2d, 0.35f );
71 | g2d.setPaint(rolloverBg);
72 | g2d.fill(new RoundRectangle2D.Double(rect.x + selectionShadeWidth, rect.y + selectionShadeWidth,
73 | rect.width - selectionShadeWidth * 2 - 1, rect.height - selectionShadeWidth * 2 - 1, 0,
74 | 0));
75 | //LafUtils.restoreComposite ( g2d, old );
76 | }
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/action/IMActionHandler.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.action;
2 |
3 | import java.lang.annotation.*;
4 |
5 | /**
6 | * @author ChenZhiHui <6208317@qq.com>
7 | * @create-time 2013-4-1
8 | */
9 | @Documented
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Target(ElementType.METHOD)
12 | public @interface IMActionHandler {
13 | String name() default "";
14 |
15 | String enabledProperty() default "";
16 |
17 | String selectedProperty() default "";
18 |
19 | @Retention(RetentionPolicy.RUNTIME)
20 | @Target(ElementType.PARAMETER)
21 | @interface Parameter {
22 | String value() default "";
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/action/IMActionHandlerProxy.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.action;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.lang.reflect.Method;
9 |
10 | /**
11 | * Project : iqq-projects
12 | * Author : 承∮诺 < 6208317@qq.com >
13 | * Created : 14-5-11
14 | * License : Apache License 2.0
15 | */
16 | public class IMActionHandlerProxy implements ActionListener {
17 | private static final Logger logger = LoggerFactory.getLogger(IMActionHandlerProxy.class.getName());
18 | private Object proxyObject;
19 | private String actionName;
20 | private Method method;
21 | private Object[] params;
22 |
23 | public IMActionHandlerProxy(Object proxyObject, String actionName, Object... params) {
24 | this.proxyObject = proxyObject;
25 | this.actionName = actionName;
26 | this.params = params;
27 |
28 | for (Method m : proxyObject.getClass().getDeclaredMethods()) {
29 | if (m.isAnnotationPresent(IMActionHandler.class)) {
30 | IMActionHandler handler = m
31 | .getAnnotation(IMActionHandler.class);
32 | if (!handler.name().isEmpty() && actionName.equals(handler.name())) {
33 | this.method = m;
34 | } else if (handler.name().isEmpty() && actionName.equals(m.getName())) {
35 | this.method = m;
36 | }
37 | if (!m.isAccessible()) {
38 | m.setAccessible(true);
39 | }
40 | }
41 | }
42 | }
43 |
44 | @Override
45 | public void actionPerformed(ActionEvent evt) {
46 | if (method == null) {
47 | throw new IllegalArgumentException("invoke IMActionHandlerProxy Error!! no method: " + actionName);
48 | }
49 | try {
50 | if (method.getParameterTypes().length == 0) {
51 | method.invoke(proxyObject);
52 | return;
53 | }
54 | Class>[] types = method.getParameterTypes();
55 | if (types[0].equals(ActionEvent.class)) {
56 | if (types.length == 1) {
57 | method.invoke(proxyObject, evt);
58 | } else {
59 | Object[] ps = new Object[params.length + 1];
60 | ps[0] = evt;
61 | for (int i = 1; i < params.length + 1; i++) {
62 | ps[i] = params[i - 1];
63 | }
64 | method.invoke(proxyObject, ps);
65 | }
66 | } else {
67 | method.invoke(proxyObject, params);
68 | }
69 | } catch (Throwable e) {
70 | logger.warn("invoke IMActionHandlerProxy Error!!", e);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/border/RoundBorder.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.border;
2 |
3 | import javax.swing.border.Border;
4 | import java.awt.*;
5 |
6 | /**
7 | * Project : iqq-projects
8 | * Author : 承∮诺 < 6208317@qq.com >
9 | * Created : 14-5-11
10 | * License : Apache License 2.0
11 | */
12 | public class RoundBorder implements Border {
13 | @Override
14 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
15 | final Graphics2D g2d = (Graphics2D) g;
16 | g2d.setPaint(new Color(160, 160, 160));
17 | g2d.drawRoundRect(x, y, width, height, 10, 10);
18 | }
19 |
20 | @Override
21 | public Insets getBorderInsets(Component c) {
22 | return new Insets(5, 5, 5, 5);
23 | }
24 |
25 | @Override
26 | public boolean isBorderOpaque() {
27 | return true;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/border/ShadeBorder.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.border;
2 |
3 | import javax.swing.border.Border;
4 | import java.awt.*;
5 |
6 | /**
7 | * Project : iqq-projects
8 | * Author : 承∮诺 < 6208317@qq.com >
9 | * Created : 14-5-11
10 | * License : Apache License 2.0
11 | */
12 | public class ShadeBorder implements Border {
13 | @Override
14 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
15 | final Graphics2D g2d = (Graphics2D) g;
16 | g2d.setPaint(new Color(160, 160, 160, 60));
17 | g2d.fillRoundRect(x, y, width, height, 10, 10);
18 | }
19 |
20 | @Override
21 | public Insets getBorderInsets(Component c) {
22 | return new Insets(10, 10, 10, 10);
23 | }
24 |
25 | @Override
26 | public boolean isBorderOpaque() {
27 | return true;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/border/TabContentPanelBorder.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.border;
2 |
3 | import org.sexydock.tabs.jhrome.JhromeContentPanelBorder;
4 |
5 | import java.awt.*;
6 | import java.awt.geom.Path2D;
7 |
8 | /**
9 | * Project : iqq-projects
10 | * Author : 承∮诺 < 6208317@qq.com >
11 | * Created : 14-5-13
12 | * License : Apache License 2.0
13 | */
14 | public class TabContentPanelBorder extends JhromeContentPanelBorder {
15 | int roundness = 3;
16 | int thickness = 0;
17 | Color outlineColor = new Color(55, 55, 55, 120);
18 | Color backgroundColor = new Color(255, 255, 255, 0);
19 |
20 | /*
21 | * (non-Javadoc)
22 | *
23 | * @see javax.swing.border.Border#paintBorder(java.awt.Component, java.awt.Graphics, int, int, int, int)
24 | */
25 | @Override
26 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
27 | Graphics2D g2 = (Graphics2D) g;
28 |
29 | int inset = Math.max(thickness - 1, 0);
30 |
31 | Path2D path = new Path2D.Double();
32 | path.moveTo(x + inset, y + height - inset - inset);
33 | path.lineTo(x + inset, y + inset + roundness);
34 | path.curveTo(x + inset, y + inset, x + inset, y + inset, x + inset + roundness, y + inset);
35 | path.lineTo(x + width - roundness - inset - inset, y + inset);
36 | path.curveTo(x + width - inset - inset, y + inset, x + width - inset - inset, y + inset, x + width - inset - inset, y + inset + roundness);
37 | path.lineTo(x + width - inset - inset, y + height - inset - inset);
38 | path.closePath();
39 |
40 | Stroke prevStroke = g2.getStroke();
41 | Paint prevPaint = g2.getPaint();
42 | Object prevAntialias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
43 | g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
44 |
45 | g2.setStroke(new BasicStroke(thickness));
46 | g2.setColor(outlineColor);
47 | g2.draw(path);
48 |
49 | g2.setColor(backgroundColor);
50 | g2.fill(path);
51 |
52 | g2.setStroke(prevStroke);
53 | g2.setPaint(prevPaint);
54 | g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, prevAntialias);
55 | }
56 |
57 | @Override
58 | public Insets getBorderInsets(Component c) {
59 | return new Insets(roundness + thickness, roundness + thickness, roundness + thickness, roundness + thickness);
60 | }
61 |
62 | @Override
63 | public boolean isBorderOpaque() {
64 | // TODO Auto-generated method stub
65 | return false;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/dialog/TipDialog.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.dialog;
2 |
3 | import com.alee.extended.panel.CenterPanel;
4 | import com.alee.extended.panel.VerticalPanel;
5 | import com.alee.laf.button.WebButton;
6 | import com.alee.laf.panel.WebPanel;
7 | import com.alee.laf.rootpane.WebFrame;
8 | import com.alee.laf.text.WebTextArea;
9 | import iqq.app.core.service.SkinService;
10 | import iqq.app.ui.IMContentPane;
11 | import iqq.app.ui.IMDialog;
12 | import iqq.app.ui.IMFrame;
13 | import iqq.app.ui.component.TitleComponent;
14 | import iqq.app.util.UIUtils;
15 |
16 | import javax.swing.*;
17 | import java.awt.*;
18 | import java.awt.event.ActionEvent;
19 | import java.awt.event.ActionListener;
20 |
21 | /**
22 | * Created by Tony on 5/22/15.
23 | */
24 | public class TipDialog extends IMDialog {
25 | private IMContentPane contentPane = new IMContentPane();
26 | private WebTextArea messageTxt;
27 |
28 | public TipDialog(IMFrame owner) {
29 | super(owner);
30 |
31 | initUI();
32 | initContent();
33 | }
34 |
35 | private void initUI() {
36 | setTitle("提示");
37 | setModal(true);
38 | setDefaultCloseOperation(WebFrame.DISPOSE_ON_CLOSE);
39 | setAlwaysOnTop(true);
40 | setPreferredSize(new Dimension(240, 160)); // 首选大小
41 | setLocation(UIUtils.getLocationForCenter(owner));
42 | pack();
43 | }
44 |
45 | @Override
46 | public void installSkin(SkinService skinService) {
47 | super.installSkin(skinService);
48 | // 背景
49 | contentPane.setPainter(skinService.getPainterByKey("skin/background"));
50 | setIconImage(getSkinService().getIconByKey("skin/skinIcon").getImage());
51 | }
52 |
53 | private void initContent() {
54 | contentPane.add(headerPanel(), BorderLayout.NORTH);
55 | contentPane.add(contentPanel(), BorderLayout.CENTER);
56 | setIMContentPane(contentPane);
57 | }
58 |
59 | private WebPanel headerPanel() {
60 | WebPanel headerPanel = new WebPanel();
61 | headerPanel.setOpaque(false);
62 | TitleComponent titleComponent = new TitleComponent(owner);
63 | titleComponent.setShowSettingButton(false);
64 | titleComponent.setShowMaximizeButton(false);
65 | titleComponent.setShowSkinButton(false);
66 | titleComponent.setShowMinimizeButton(false);
67 | headerPanel.add(titleComponent, BorderLayout.NORTH);
68 | return headerPanel;
69 | }
70 |
71 | private WebPanel contentPanel() {
72 | WebPanel contentPanel = new WebPanel();
73 | messageTxt = new WebTextArea();
74 | messageTxt.setEditable(false);
75 | messageTxt.setLineWrap(true);
76 | messageTxt.setWrapStyleWord(true);
77 | messageTxt.setBackground(getBackground());
78 | messageTxt.setAlignmentX(SwingConstants.CENTER);
79 | messageTxt.setMargin(20);
80 | WebButton okBtn = new WebButton("确定");
81 | okBtn.setPreferredWidth(30);
82 | okBtn.addActionListener(new ActionListener() {
83 | @Override
84 | public void actionPerformed(ActionEvent e) {
85 | dispose();
86 | }
87 | });
88 | contentPanel.add(new CenterPanel(messageTxt), BorderLayout.CENTER);
89 | contentPanel.add(okBtn, BorderLayout.PAGE_END);
90 | return contentPanel;
91 | }
92 |
93 | /**
94 | * 设置提示信息
95 | *
96 | * @param text
97 | */
98 | public void setMessage(String text) {
99 | messageTxt.setText(text);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/event/UIEvent.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.event;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import iqq.api.common.EventBase;
20 |
21 | import java.io.Serializable;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 |
25 | /**
26 | * Project : iqq
27 | * Author : solosky < solosky772@qq.com >
28 | * Created : 5/3/14
29 | * License : Apache License 2.0
30 | */
31 | public class UIEvent extends EventBase implements Serializable {
32 | /**
33 | * 事件ID,定义在IMEventID
34 | */
35 | private UIEventType type;
36 |
37 | public UIEvent(UIEventType type) {
38 | this.type = type;
39 | }
40 |
41 | public UIEvent() {
42 | }
43 |
44 | public UIEvent(UIEventType type, Object target) {
45 | this.type = type;
46 | this.target = target;
47 | }
48 |
49 | public UIEventType getType() {
50 | return type;
51 | }
52 |
53 | public void setType(UIEventType type) {
54 | this.type = type;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/event/UIEventDispatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.action
21 | * File : IMEventHandlerProxy.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-3-16
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.event;
27 |
28 | import org.slf4j.Logger;
29 | import org.slf4j.LoggerFactory;
30 |
31 | import java.lang.reflect.Method;
32 | import java.util.HashMap;
33 | import java.util.Map;
34 |
35 | /**
36 | * 使用这个类简化事件的注册,分发
37 | * 只需在被代理的类使用@IMEventHandler注解需要处理的事件类型即可
38 | *
39 | * @author solosky
40 | */
41 | public class UIEventDispatcher implements UIEventListener {
42 | private static final Logger LOG = LoggerFactory.getLogger(UIEventDispatcher.class);
43 | private Map methodMap = new HashMap();
44 | private Object target;
45 |
46 | public UIEventDispatcher(Object target) {
47 | this.target = target;
48 | for (Method m : target.getClass().getDeclaredMethods()) {
49 | if (m.isAnnotationPresent(UIEventHandler.class)) {
50 | UIEventHandler handler = m.getAnnotation(UIEventHandler.class);
51 | this.methodMap.put(handler.value(), m);
52 | if (!m.isAccessible()) {
53 | m.setAccessible(true);
54 | }
55 | }
56 | }
57 | for (Method m : target.getClass().getMethods()) {
58 | if (m.isAnnotationPresent(UIEventHandler.class)) {
59 | UIEventHandler handler = m.getAnnotation(UIEventHandler.class);
60 | this.methodMap.put(handler.value(), m);
61 | if (!m.isAccessible()) {
62 | m.setAccessible(true);
63 | }
64 | }
65 | }
66 | }
67 |
68 | public UIEventType[] getEventTypes() {
69 | return methodMap.keySet().toArray(new UIEventType[]{});
70 | }
71 |
72 | @Override
73 | public void onUIEvent(UIEvent imEvent) {
74 | Method m = methodMap.get(imEvent.getType());
75 | if (m != null) {
76 | try {
77 | m.invoke(target, imEvent);
78 | } catch (Throwable e) {
79 | LOG.warn("invoke UIEventHandler Error!! {}.{}(..)", getClass(), m.getName(), e);
80 | }
81 | } else {
82 | LOG.warn("UIEventHandler Not Found!! imEvent = {}", imEvent);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/event/UIEventHandler.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.event; /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 | import java.lang.annotation.Target;
22 |
23 | /**
24 | * 事件处理注解,如果在方法上写上了这个注解,则说明此方法处理对应的消息
25 | *
26 | * Project : iqq
27 | * Author : solosky < solosky772@qq.com >
28 | * Created : 4/13/14
29 | * License : Apache License 2.0
30 | */
31 | @Target(ElementType.METHOD)
32 | @Retention(RetentionPolicy.RUNTIME)
33 | public @interface UIEventHandler {
34 | public UIEventType value();
35 | }
36 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/event/UIEventListener.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.event;
2 |
3 | /**
4 | * IM事件监听器
5 | */
6 | public interface UIEventListener {
7 | /**
8 | * 触发事件回掉
9 | *
10 | * @param imEvent
11 | */
12 | public void onUIEvent(UIEvent imEvent);
13 | }
14 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/event/args/LoginInfoParam.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.event.args;
2 | /*
3 | * Licensed to the Apache Software Foundation (ASF) under one or more
4 | * contributor license agreements. See the NOTICE file distributed with
5 | * this work for additional information regarding copyright ownership.
6 | * The ASF licenses this file to You under the Apache License, Version 2.0
7 | * (the "License"); you may not use this file except in compliance with
8 | * 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 |
19 | import iqq.api.bean.IMStatus;
20 |
21 | import java.io.Serializable;
22 |
23 | /**
24 | * Project : iqq
25 | * Author : solosky < solosky772@qq.com >
26 | * Created : 6/14/14
27 | * License : Apache License 2.0
28 | */
29 | public class LoginInfoParam implements Serializable {
30 | private String username;
31 | private String password;
32 | private IMStatus status;
33 | private boolean remPwd;
34 |
35 | public String getUsername() {
36 | return username;
37 | }
38 |
39 | public void setUsername(String username) {
40 | this.username = username;
41 | }
42 |
43 | public String getPassword() {
44 | return password;
45 | }
46 |
47 | public void setPassword(String password) {
48 | this.password = password;
49 | }
50 |
51 | public IMStatus getStatus() {
52 | return status;
53 | }
54 |
55 | public void setStatus(IMStatus status) {
56 | this.status = status;
57 | }
58 |
59 | public boolean isRemPwd() {
60 | return remPwd;
61 | }
62 |
63 | public void setRemPwd(boolean remPwd) {
64 | this.remPwd = remPwd;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/ChatPane.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.chat;
2 |
3 | import iqq.app.core.service.SkinService;
4 | import iqq.app.ui.IMContentPane;
5 | import iqq.app.ui.border.TabContentPanelBorder;
6 | import iqq.app.ui.component.TitleComponent;
7 | import iqq.app.ui.frame.ChatFrame;
8 | import org.sexydock.tabs.jhrome.JhromeTabBorderAttributes;
9 | import org.sexydock.tabs.jhrome.JhromeTabbedPaneUI;
10 |
11 | import javax.swing.*;
12 | import java.awt.*;
13 |
14 | /**
15 | * Project : iqq-projects
16 | * Author : 承∮诺 < 6208317@qq.com >
17 | * Created : 14-5-10
18 | * License : Apache License 2.0
19 | */
20 | public class ChatPane extends IMContentPane {
21 |
22 | private ChatFrame frame;
23 | private JTabbedPane tabbedPane;
24 | private JButton settingButton;
25 |
26 | public ChatPane(ChatFrame chatFrame) {
27 | super();
28 |
29 | frame = chatFrame;
30 |
31 | initTabbedPane();
32 | }
33 |
34 | public JTabbedPane getTabbedPane() {
35 | return tabbedPane;
36 | }
37 |
38 | private void initTabbedPane() {
39 | TitleComponent titleComponent = new TitleComponent(frame);
40 | titleComponent.setShowSkinButton(false);
41 | titleComponent.setShowSettingButton(false);
42 | //titleComponent.setShowTitle(false);
43 | add(titleComponent, BorderLayout.NORTH);
44 |
45 | JhromeTabBorderAttributes.SELECTED_BORDER.topColor = new Color(255, 255, 255, 120);
46 | JhromeTabBorderAttributes.SELECTED_BORDER.bottomColor = new Color(255, 255, 255, 0);
47 | JhromeTabBorderAttributes.SELECTED_BORDER.shadowColor = new Color(55, 55, 55, 50);
48 | JhromeTabBorderAttributes.SELECTED_BORDER.outlineColor = new Color(55, 55, 55, 100);
49 | JhromeTabBorderAttributes.UNSELECTED_BORDER.topColor = new Color(255, 255, 255, 40);
50 | JhromeTabBorderAttributes.UNSELECTED_BORDER.bottomColor = new Color(255, 255, 255, 0);
51 | JhromeTabBorderAttributes.UNSELECTED_BORDER.shadowColor = new Color(55, 55, 55, 20);
52 | JhromeTabBorderAttributes.UNSELECTED_BORDER.outlineColor = new Color(55, 55, 55, 100);
53 | JhromeTabBorderAttributes.UNSELECTED_ROLLOVER_BORDER.topColor = new Color(255, 255, 255, 160);
54 | JhromeTabBorderAttributes.UNSELECTED_ROLLOVER_BORDER.bottomColor = new Color(255, 255, 255, 50);
55 | JhromeTabbedPaneUI ui = new JhromeTabbedPaneUI();
56 | tabbedPane = new JTabbedPane();
57 | tabbedPane.setUI(ui);
58 | tabbedPane.setOpaque(false);
59 | tabbedPane.putClientProperty(JhromeTabbedPaneUI.TAB_CLOSE_BUTTONS_VISIBLE, true);
60 | tabbedPane.putClientProperty(JhromeTabbedPaneUI.NEW_TAB_BUTTON_VISIBLE, true);
61 | tabbedPane.putClientProperty(JhromeTabbedPaneUI.CONTENT_PANEL_BORDER, new TabContentPanelBorder());
62 | settingButton = ui.getNewTabButton();
63 | add(tabbedPane, BorderLayout.CENTER);
64 | }
65 |
66 | @Override
67 | public void installSkin(SkinService skinService) {
68 | super.installSkin(skinService);
69 | // 背景
70 | this.setPainter(skinService.getPainterByKey("skin/background"));
71 | settingButton.setIcon(skinService.getIconByKey("chat/settingIcon", 14, 14));
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/RoomPanel.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.chat;
2 |
3 | import iqq.api.bean.IMRoom;
4 |
5 | /**
6 | * Project : iqq-projects
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-5-11
9 | * License : Apache License 2.0
10 | */
11 | public class RoomPanel extends BasicPanel {
12 |
13 | public RoomPanel(IMRoom entity) {
14 | super(entity);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/UserPanel.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.chat;
2 |
3 | import com.alee.laf.button.WebButton;
4 | import com.alee.laf.toolbar.WebToolBar;
5 | import iqq.api.bean.IMMsg;
6 | import iqq.api.bean.IMUser;
7 | import iqq.api.bean.content.IMContentItem;
8 | import iqq.api.bean.content.IMTextItem;
9 | import iqq.app.core.service.SkinService;
10 |
11 | import java.util.ArrayList;
12 | import java.util.Date;
13 |
14 | /**
15 | * Project : iqq-projects
16 | * Author : 承∮诺 < 6208317@qq.com >
17 | * Created : 14-5-11
18 | * License : Apache License 2.0
19 | */
20 | public class UserPanel extends BasicPanel {
21 |
22 | protected WebButton shakeBtn;
23 |
24 | public UserPanel(IMUser entity) {
25 | super(entity);
26 |
27 | // test();
28 | }
29 |
30 | private void test() {
31 | IMMsg msg = new IMMsg();
32 | msg.setSender((IMUser) entity);
33 | java.util.List contents = new ArrayList();
34 | IMTextItem text = new IMTextItem("test content...");
35 | contents.add(text);
36 | msg.setContents(contents);
37 | msg.setDate(new Date());
38 | msg.setState(IMMsg.State.READ);
39 | showMsg(msg);
40 | showMsg(msg);
41 | showMsg(msg);
42 | showMsg(msg);
43 | showMsg(msg);
44 | }
45 |
46 | public IMUser getUser() {
47 | return (IMUser) this.entity;
48 | }
49 |
50 | @Override
51 | protected void initInputToolbar(WebToolBar inputToolbar) {
52 | super.initInputToolbar(inputToolbar);
53 |
54 | shakeBtn = new WebButton();
55 |
56 | setInputButtonStyle(shakeBtn);
57 |
58 | // 震动
59 | inputToolbar.add(3, shakeBtn);
60 | }
61 |
62 | @Override
63 | public void installSkin(SkinService skinService) {
64 | super.installSkin(skinService);
65 |
66 | shakeBtn.setIcon(skinService.getIconByKey("chat/toolbar/shake"));
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/msg/MsgGroupPanel.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.chat.msg;
2 |
3 | import com.alee.extended.panel.GroupPanel;
4 | import iqq.api.bean.IMMsg;
5 | import iqq.api.bean.IMUser;
6 |
7 | import java.awt.*;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * @author ChenZhiHui <6208317@qq.com>
13 | * @create-time 2013-3-24
14 | */
15 | public class MsgGroupPanel extends GroupPanel {
16 | private static final long serialVersionUID = -3757572461881253014L;
17 |
18 | public MsgGroupPanel() {
19 | super(false);
20 | setOpaque(true);
21 | setBackground(new Color(245, 245, 245));
22 | }
23 |
24 | public void updateMsg(IMMsg msg) {
25 | for (Component comp : getComponents()) {
26 | if (comp instanceof MsgPane) {
27 | MsgPane pane = (MsgPane) comp;
28 | IMMsg cur = pane.getMsg();
29 | long msgId = cur.getId();
30 | if (msgId == msg.getId()) {
31 | pane.invalidate();
32 | return;
33 | }
34 | }
35 | }
36 | }
37 |
38 | public void updateUser(IMUser user) {
39 | for (Component comp : getComponents()) {
40 | if (comp instanceof MsgPane) {
41 | MsgPane pane = (MsgPane) comp;
42 | IMMsg cur = pane.getMsg();
43 | IMUser sender = cur.getSender();
44 | if (user.equals(sender)) {
45 | pane.invalidate();
46 | }
47 | }
48 | }
49 | }
50 |
51 | public List getMsgList() {
52 | List list = new ArrayList();
53 | for (Component comp : getComponents()) {
54 | if (comp instanceof MsgPane) {
55 | MsgPane pane = (MsgPane) comp;
56 | list.add(pane.getMsg());
57 | }
58 | }
59 | return list;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/picloader/PicLoadListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.picloader
21 | * File : PicLoadListener.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-20
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.picloader;
27 |
28 | import java.awt.*;
29 |
30 | /**
31 | *
32 | * 图片加载监听器,UI通过这个监听器获得图片加载进度和结果
33 | *
34 | * @author solosky
35 | *
36 | */
37 | public interface PicLoadListener {
38 | public void onProgress(long current, long total);
39 |
40 | public void onError(Throwable t);
41 |
42 | public void onSuccess(Image image);
43 | }
44 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/picloader/PicLoadState.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.picloader
21 | * File : PicLoadState.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-20
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.picloader;
27 |
28 | /**
29 | *
30 | * 加载状态
31 | *
32 | * @author solosky
33 | *
34 | */
35 | public enum PicLoadState {
36 | PENDING,
37 | SUCCESS,
38 | ERROR,
39 | LOADING,
40 | UPLOADING
41 | }
42 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/picloader/PicLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.picloader
21 | * File : PicLoader.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-20
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.picloader;
27 |
28 | import iqq.api.bean.content.IMContentItem;
29 |
30 | import java.awt.*;
31 | import java.io.Serializable;
32 |
33 | /**
34 | *
35 | * 图片加载或者上传接口
36 | * 可以是加载网络上的图片,也可以是加载本地图片
37 | * 需序列话保存在本地,实现是注意考虑序列号问题
38 | *
39 | * @author solosky
40 | *
41 | */
42 | public interface PicLoader extends Serializable {
43 | public void loadPic();
44 |
45 | public void sendToServer();
46 |
47 | public void addListener(PicLoadListener listener);
48 |
49 | public void removeListener(PicLoadListener listener);
50 |
51 | public IMContentItem getContentItem();
52 |
53 | public PicLoadState getState();
54 |
55 | public Image getPic();
56 | }
57 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/picloader/PicLoaderFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.picloader
21 | * File : PicLoaderFactory.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-20
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.picloader;
27 |
28 | import iqq.api.bean.IMAccount;
29 | import iqq.api.bean.IMMsg;
30 | import iqq.api.bean.content.IMContentItem;
31 | import iqq.api.bean.content.IMPictureItem;
32 |
33 | import java.io.File;
34 |
35 | /**
36 | *
37 | * 工厂类,根据QQMsg和ContentItem来创建Loader
38 | *
39 | * @author solosky
40 | *
41 | */
42 | public class PicLoaderFactory {
43 | /***
44 | * 通过消息中的一个对象来创建PicLoader
45 | * @param item CFaceItem或OffPicItem, 其他抛出异常 IllegalArgumentException
46 | * @param msg 接收到的QQ消息对象
47 | * @return
48 | */
49 | public static PicLoader createLoader(IMContentItem item, IMMsg msg) {
50 | if (item instanceof UserPicLoader) {
51 | return new UserPicLoader((IMPictureItem) item, msg.getSender());
52 | }
53 | throw new IllegalArgumentException("invalid content item:" + item);
54 | }
55 |
56 | /***
57 | * 通过要发送消息的对象来创建对应的PicLoader
58 | * @param picFile 图片文件
59 | * @param target 发送对象,QQUser, QQGroup, QQDiscuz, 其他抛出异常 IllegalArgumentException
60 | * @param self 用户自己对象
61 | * @return
62 | */
63 | public static PicLoader createLoader(File picFile, Object target, IMAccount self) {
64 |
65 | throw new IllegalArgumentException("invalid target:" + target);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/picloader/UserPicLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.picloader
21 | * File : CFacePicLoader.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-20
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.picloader;
27 |
28 | import iqq.api.bean.IMEntity;
29 | import iqq.api.bean.content.IMPictureItem;
30 | import iqq.api.event.IMEvent;
31 |
32 | import java.io.File;
33 |
34 | /**
35 | *
36 | * 用户图片,其实也是CFace,但获取的地址和方式不同
37 | *
38 | * @author solosky
39 | *
40 | */
41 | public class UserPicLoader extends AbstractPicLoader {
42 | private static final long serialVersionUID = 1L;
43 | private File file;
44 | private IMEntity owner;
45 |
46 | public UserPicLoader(IMPictureItem item, IMEntity owner) {
47 | this.file = item.getFile();
48 | this.owner = owner;
49 | }
50 |
51 | @Override
52 | protected void doLoadFromServer() throws Exception {
53 |
54 |
55 | }
56 |
57 | @Override
58 | protected void doSendToServer() throws Exception {
59 | throw new UnsupportedOperationException("not supported!!");
60 | }
61 |
62 | @Override
63 | protected boolean isMyEvent(IMEvent event) {
64 | return false;
65 | }
66 |
67 |
68 | @Override
69 | public void sendToServer() {
70 |
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UIBasicItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : AbstractItem.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-8
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 | import com.alee.extended.panel.GroupPanel;
29 |
30 | /**
31 | *
32 | * 抽象的富文本对象,可以作为子类继承,实现了保存IMContext的基本方法
33 | *
34 | * @author solosky
35 | *
36 | */
37 | public abstract class UIBasicItem implements UIRichItem {
38 | private static final long serialVersionUID = 1L;
39 |
40 | protected static class UIBasicComponent extends GroupPanel implements UIRichComponent {
41 | private static final long serialVersionUID = 1L;
42 | private UIRichItem richItem;
43 |
44 | public UIBasicComponent(UIRichItem richItem) {
45 | this.richItem = richItem;
46 | }
47 |
48 | @Override
49 | public UIRichItem getRichItem() {
50 | return richItem;
51 | }
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UIFaceItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : UIFaceItem.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-8
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 | import javax.swing.*;
29 |
30 | /**
31 | *
32 | * 表情对象
33 | *
34 | * @author solosky
35 | *
36 | */
37 | public class UIFaceItem extends UIBasicItem {
38 | private static final long serialVersionUID = 1L;
39 | private int faceId;
40 |
41 | public UIFaceItem(int faceId) {
42 | this.faceId = faceId;
43 | }
44 |
45 | public int getFaceId() {
46 | return faceId;
47 | }
48 |
49 | @Override
50 | public void insertTo(JTextPane pane) throws Exception {
51 | //FaceIcon icon = FaceWindow.getFaceIconById(faceId);
52 | //pane.insertComponent(new UIFaceComponent(icon));
53 | }
54 |
55 | private class UIFaceComponent extends JLabel implements UIRichComponent {
56 | /*
57 | UIFaceComponent(FaceIcon icon){
58 | super();
59 | setIcon(icon.getIcon());
60 | }
61 | */
62 | @Override
63 | public UIRichItem getRichItem() {
64 | return UIFaceItem.this;
65 | }
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UILinkItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : UILinkItem.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-9
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 | import javax.swing.*;
29 | import javax.swing.text.Document;
30 | import javax.swing.text.SimpleAttributeSet;
31 | import javax.swing.text.StyleConstants;
32 | import javax.swing.text.html.HTML;
33 | import java.awt.*;
34 |
35 | /**
36 | *
37 | * 超链接组件
38 | *
39 | * @author solosky
40 | *
41 | */
42 | public class UILinkItem extends UIBasicItem {
43 | private static final long serialVersionUID = 1L;
44 | private String link;
45 | private transient Action action;
46 |
47 | public UILinkItem(String link) {
48 | this.link = link;
49 | }
50 |
51 | public UILinkItem(String link, Action action) {
52 | this.link = link;
53 | this.action = action;
54 | }
55 |
56 | @Override
57 | public void insertTo(final JTextPane pane) throws Exception {
58 | Document doc = pane.getDocument();
59 | SimpleAttributeSet attrs = new SimpleAttributeSet();
60 | StyleConstants.setUnderline(attrs, true);
61 | StyleConstants.setForeground(attrs, Color.BLUE);// unvisited color
62 | // StyleConstants.setFontSize(null, 13);
63 | attrs.addAttribute(HTML.Attribute.HREF, link);
64 | if (action != null) {
65 | attrs.addAttribute("action", action);
66 | attrs.addAttribute("self", this);
67 | }
68 | doc.insertString(doc.getLength(), link, attrs);
69 | }
70 |
71 | public String getLink() {
72 | return link;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UIRichComponent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : UIRichComponent.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-9
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 | /**
29 | *
30 | * UI图形化组件,是具体加入RichPane的图形组件
31 | * 所有加入RichPane的图形组件都需要实现这个接口,便于获得UIRichItem对象
32 | *
33 | * @author solosky
34 | *
35 | */
36 | public interface UIRichComponent {
37 | public UIRichItem getRichItem();
38 | }
39 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UIRichItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : RichItem.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-8
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 | import javax.swing.*;
29 | import java.io.Serializable;
30 |
31 | /**
32 | *
33 | * 富文本编辑器内容对象
34 | * 注意实现此接口需要考虑到序列化的问题
35 | *
36 | * @author solosky
37 | *
38 | */
39 | public interface UIRichItem extends Serializable {
40 |
41 | /***
42 | * 把当前对象加入到TextPane里面
43 | * @param pane
44 | */
45 | public void insertTo(JTextPane pane) throws Exception;
46 | }
47 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UISkinPicItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : UIResPicItem.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-9
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 |
29 | import iqq.app.core.context.IMContext;
30 | import iqq.app.core.service.SkinService;
31 | import iqq.app.core.service.impl.SkinServiceImpl;
32 |
33 | import javax.swing.*;
34 |
35 | /**
36 | *
37 | * 插入程序皮肤本地资源
38 | * 通常这些图片都较小,并且都有缓存,直接添加即可
39 | *
40 | * @author solosky
41 | *
42 | */
43 | public class UISkinPicItem extends UIBasicItem {
44 | private static final long serialVersionUID = 1L;
45 | private String picName;
46 |
47 | public UISkinPicItem(String picName) {
48 | this.picName = picName;
49 | }
50 |
51 | @Override
52 | public void insertTo(JTextPane pane) throws Exception {
53 | SkinService skins = IMContext.getBean(SkinServiceImpl.class);
54 | ImageIcon pic = skins.getIconByKey(picName);
55 | pane.insertComponent(new UISkinComponent(pic));
56 | }
57 |
58 | private class UISkinComponent extends JLabel implements UIRichComponent {
59 | private static final long serialVersionUID = 1L;
60 |
61 | UISkinComponent(ImageIcon pic) {
62 | super();
63 | setIcon(pic);
64 | }
65 |
66 | @Override
67 | public UIRichItem getRichItem() {
68 | return UISkinPicItem.this;
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/chat/rich/UITextItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : IQQ_V2.1
20 | * Package : iqq.app.ui.content.chat.rich
21 | * File : TextItem.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-8
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.ui.frame.panel.chat.rich;
27 |
28 | import javax.swing.*;
29 | import javax.swing.text.StyledDocument;
30 |
31 | /**
32 | *
33 | * 普通文本对象
34 | *
35 | * @author solosky
36 | *
37 | */
38 | public class UITextItem extends UIBasicItem {
39 | private static final long serialVersionUID = 1L;
40 | private String text;
41 |
42 | public UITextItem(String text) {
43 | this.text = text;
44 | }
45 |
46 | @Override
47 | public void insertTo(JTextPane pane) throws Exception {
48 | StyledDocument styledDocument = pane.getStyledDocument();
49 | styledDocument.insertString(styledDocument.getLength(), text, pane.getCharacterAttributes());
50 | }
51 |
52 | public String getText() {
53 | return text;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/login/LoginingPane.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.login;
2 |
3 | import iqq.app.ui.IMContentPane;
4 |
5 | /**
6 | * Project : iqq-projects
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-6-17
9 | * License : Apache License 2.0
10 | */
11 | public class LoginingPane extends IMContentPane {
12 |
13 | public LoginingPane() {
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/main/FooterPanel.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.main;
2 |
3 | import com.alee.laf.button.WebButton;
4 | import com.alee.laf.toolbar.ToolbarStyle;
5 | import com.alee.laf.toolbar.WebToolBar;
6 | import iqq.app.core.context.IMContext;
7 | import iqq.app.core.service.SkinService;
8 | import iqq.app.ui.IMPanel;
9 | import iqq.app.ui.frame.MainFrame;
10 | import iqq.app.ui.manager.FrameManager;
11 |
12 | import java.awt.*;
13 | import java.awt.event.ActionEvent;
14 | import java.awt.event.ActionListener;
15 |
16 | /**
17 | * Project : iqq-projects
18 | * Author : 承∮诺 < 6208317@qq.com >
19 | * Created : 14-5-8
20 | * License : Apache License 2.0
21 | */
22 | public class FooterPanel extends IMPanel {
23 | private MainFrame frame;
24 | private WebToolBar toolBar = new WebToolBar();
25 |
26 | private WebButton add = new WebButton();
27 | private WebButton mail = new WebButton();
28 | private WebButton qzone = new WebButton();
29 | private WebButton weibo = new WebButton();
30 | private WebButton msg = new WebButton();
31 | private WebButton setting = new WebButton();
32 |
33 |
34 | public FooterPanel(MainFrame frame) {
35 | super();
36 | this.frame = frame;
37 |
38 | initButtons();
39 | initToolbar();
40 | inttAction();
41 | }
42 |
43 | private void inttAction() {
44 | add.addActionListener(new ActionListener() {
45 | @Override
46 | public void actionPerformed(ActionEvent e) {
47 | IMContext.getBean(FrameManager.class).showAddFriend();
48 | }
49 | });
50 | }
51 |
52 | private void initButtons() {
53 |
54 | }
55 |
56 | private void initToolbar() {
57 | toolBar.setFloatable(false);
58 | toolBar.setToolbarStyle(ToolbarStyle.attached);
59 | toolBar.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
60 | toolBar.setTopBgColor(new Color(255, 255, 255, 130));
61 | toolBar.setBottomBgColor(new Color(255, 255, 255, 130));
62 | toolBar.setOpaque(false);
63 |
64 | toolBar.add(setting);
65 | toolBar.add(msg);
66 | toolBar.addSeparator();
67 | toolBar.add(weibo);
68 | toolBar.add(qzone);
69 | toolBar.add(mail);
70 | toolBar.addSeparator();
71 | toolBar.addToEnd(add);
72 | toolBar.setPreferredSize(new Dimension(-1, 26));
73 |
74 | setButtonStyle(add, mail, qzone, weibo, msg, setting);
75 |
76 | add(toolBar);
77 | }
78 |
79 | protected void setButtonStyle(WebButton... bs) {
80 | for (WebButton b : bs) {
81 | b.setPreferredSize(new Dimension(40, 40));
82 | b.setRound(2);
83 | b.setRolloverDecoratedOnly(true);
84 | b.setBackground(new Color(0, 0, 0, 0));
85 | }
86 | }
87 |
88 | @Override
89 | public void installSkin(SkinService skinService) {
90 | super.installSkin(skinService);
91 |
92 | add.setIcon(skinService.getIconByKey("main/toolbar/add"));
93 | mail.setIcon(skinService.getIconByKey("main/toolbar/mail"));
94 | qzone.setIcon(skinService.getIconByKey("main/toolbar/qzone"));
95 | weibo.setIcon(skinService.getIconByKey("main/toolbar/weibo"));
96 | msg.setIcon(skinService.getIconByKey("main/toolbar/msg"));
97 | setting.setIcon(skinService.getIconByKey("main/toolbar/setting"));
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/frame/panel/main/MainPane.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.frame.panel.main;
2 |
3 | import iqq.app.core.service.SkinService;
4 | import iqq.app.ui.IMContentPane;
5 | import iqq.app.ui.frame.MainFrame;
6 |
7 | import java.awt.*;
8 |
9 | /**
10 | * Project : iqq-projects
11 | * Author : 承∮诺 < 6208317@qq.com >
12 | * Created : 14-5-5
13 | * License : Apache License 2.0
14 | */
15 | public class MainPane extends IMContentPane {
16 |
17 | private MainFrame frame;
18 | private HeaderPanel headerPanel;
19 | private MiddlePanel middlePanel;
20 | private FooterPanel footerPanel;
21 |
22 | public MainPane(MainFrame mainFrame) {
23 | frame = mainFrame;
24 |
25 | headerPanel = new HeaderPanel(frame);
26 | middlePanel = new MiddlePanel(frame);
27 | footerPanel = new FooterPanel(frame);
28 |
29 | this.add(headerPanel, BorderLayout.NORTH);
30 | this.add(footerPanel, BorderLayout.SOUTH);
31 | this.add(middlePanel, BorderLayout.CENTER);
32 | }
33 |
34 | @Override
35 | public void installSkin(SkinService skinService) {
36 | // 背景
37 | this.setPainter(skinService.getPainterByKey("skin/background"));
38 | headerPanel.installSkin(skinService);
39 | middlePanel.installSkin(skinService);
40 | footerPanel.installSkin(skinService);
41 | }
42 |
43 | public HeaderPanel getHeaderPanel() {
44 | return headerPanel;
45 | }
46 |
47 | public void setHeaderPanel(HeaderPanel headerPanel) {
48 | this.headerPanel = headerPanel;
49 | }
50 |
51 | public MiddlePanel getMiddlePanel() {
52 | return middlePanel;
53 | }
54 |
55 | public void setMiddlePanel(MiddlePanel middlePanel) {
56 | this.middlePanel = middlePanel;
57 | }
58 |
59 | public FooterPanel getFooterPanel() {
60 | return footerPanel;
61 | }
62 |
63 | public void setFooterPanel(FooterPanel footerPanel) {
64 | this.footerPanel = footerPanel;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/manager/ChatManager.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.manager;
2 |
3 | import iqq.api.bean.IMBuddy;
4 | import iqq.api.bean.IMEntity;
5 | import iqq.api.bean.IMRoom;
6 | import iqq.api.bean.IMUser;
7 | import iqq.app.core.service.EventService;
8 | import iqq.app.ui.event.UIEvent;
9 | import iqq.app.ui.event.UIEventType;
10 | import iqq.app.ui.frame.ChatFrame;
11 | import iqq.app.ui.frame.panel.chat.BasicPanel;
12 | import iqq.app.ui.frame.panel.chat.RoomPanel;
13 | import iqq.app.ui.frame.panel.chat.UserPanel;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 | import org.springframework.stereotype.Component;
17 |
18 | import javax.annotation.Resource;
19 | import java.util.HashMap;
20 | import java.util.Map;
21 |
22 | /**
23 | * 聊天窗口管理类,用于管理聊天对话
24 | *
25 | * Project : iqq-projects
26 | * Author : 承∮诺 < 6208317@qq.com >
27 | * Created : 14-5-12
28 | * License : Apache License 2.0
29 | */
30 | @Component
31 | public class ChatManager {
32 | private final Logger LOG = LoggerFactory.getLogger(ChatManager.class);
33 | private ChatFrame chatFrame;
34 | private Map entityMap;
35 | @Resource
36 | private EventService eventService;
37 |
38 | public void addChat(IMEntity entity) {
39 | if (chatFrame == null) {
40 | chatFrame = new ChatFrame();
41 | entityMap = new HashMap();
42 | LOG.debug("创建了一个聊天窗口界面");
43 | }
44 |
45 | if (!entityMap.containsKey(entity)) {
46 | if (entity instanceof IMUser) {
47 | // 用户对话
48 | UserPanel entityPanel = new UserPanel((IMUser) entity);
49 | entityMap.put(entity, entityPanel);
50 | chatFrame.addBuddyPane((IMBuddy) entity, entityPanel);
51 | } else if (entity instanceof IMRoom) {
52 | // 聊天室对话
53 | RoomPanel entityPanel = new RoomPanel((IMRoom) entity);
54 | entityMap.put(entity, entityPanel);
55 | chatFrame.addRoomPane((IMRoom) entity, entityPanel);
56 | } else {
57 | LOG.warn("未知的聊天实体类,无法打开聊天对话");
58 | }
59 | } else {
60 | // 已经打开了对话,直接进行选中状态
61 | chatFrame.setSelectedChat(entityMap.get(entity));
62 | }
63 | if (!chatFrame.isVisible()) {
64 | chatFrame.setVisible(true);
65 | }
66 |
67 | // 打开了聊天对话
68 | eventService.broadcast(new UIEvent(UIEventType.SHOW_CHAT, entity));
69 | }
70 |
71 | /**
72 | * 删除了一个对话
73 | *
74 | * @param entity
75 | */
76 | public void removeChat(IMEntity entity) {
77 | entityMap.remove(entity);
78 |
79 | // 关闭了聊天对话
80 | eventService.broadcast(new UIEvent(UIEventType.CLOSE_CHAT, entity));
81 | }
82 |
83 | /**
84 | * 对话窗口已经关闭,进行清除处理
85 | */
86 | public void clearChats() {
87 | for (IMEntity entity : entityMap.keySet()) {
88 | removeChat(entity);
89 | }
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/manager/FrameManager.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.manager;
2 |
3 | import iqq.api.bean.IMBuddy;
4 | import iqq.api.bean.IMEntity;
5 | import iqq.api.bean.IMUser;
6 | import iqq.app.ui.frame.*;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.util.Map;
10 | import java.util.Objects;
11 |
12 | /**
13 | * Created by Tony on 4/6/15.
14 | */
15 | @Component
16 | public class FrameManager {
17 |
18 | private LoginFrame loginFrame = null;
19 | private VerifyFrame verifyFrame = null;
20 | private AddFriendFrame addFriendFrame = null;
21 | private ChooseCategoryFrame chooseCateFrame = null;
22 | private GetFriendRequestFrame getFriendRequestFrame = null;
23 |
24 | public void showLogin() {
25 | if (loginFrame == null) {
26 | loginFrame = new LoginFrame();
27 | loginFrame.setVisible(true);
28 | } else if (!loginFrame.isVisible()) {
29 | loginFrame.setVisible(true);
30 | }
31 | }
32 |
33 | public void hideLogin() {
34 | if (loginFrame != null) {
35 | loginFrame.setVisible(false);
36 | }
37 | }
38 |
39 | public void disposeLogin() {
40 | if (loginFrame != null) {
41 | loginFrame.dispose();
42 | loginFrame = null;
43 | }
44 | }
45 |
46 | public void showVerify() {
47 | if (verifyFrame == null) {
48 | verifyFrame = new VerifyFrame();
49 | verifyFrame.setVisible(true);
50 | } else if (!verifyFrame.isVisible()) {
51 | verifyFrame.setVisible(true);
52 | }
53 | }
54 |
55 | public void hideVerify() {
56 | if (verifyFrame != null) {
57 | verifyFrame.setVisible(false);
58 | }
59 | }
60 |
61 | public void showAddFriend() {
62 | if (addFriendFrame == null) {
63 | addFriendFrame = new AddFriendFrame();
64 | addFriendFrame.setVisible(true);
65 | } else if (!addFriendFrame.isVisible()) {
66 | addFriendFrame.setVisible(true);
67 | }
68 | }
69 |
70 | public void hideAddFriend() {
71 | if (addFriendFrame != null) {
72 | addFriendFrame.setVisible(false);
73 | }
74 | }
75 |
76 | public void showChooseCate(String id) {
77 | if (chooseCateFrame == null) {
78 | chooseCateFrame = new ChooseCategoryFrame(id);
79 | chooseCateFrame.setVisible(true);
80 | } else if (!chooseCateFrame.isVisible()) {
81 | chooseCateFrame.setVisible(true);
82 | }
83 | }
84 |
85 | public void hideChooseCate() {
86 | if (chooseCateFrame != null) {
87 | chooseCateFrame.setVisible(false);
88 | }
89 | }
90 |
91 | public void showGetFriendRequest(IMBuddy buddy, String buddyRequestId) {
92 | if (getFriendRequestFrame == null) {
93 | getFriendRequestFrame = new GetFriendRequestFrame(buddy, buddyRequestId);
94 | getFriendRequestFrame.setVisible(true);
95 | } else if (!getFriendRequestFrame.isVisible()) {
96 | getFriendRequestFrame.setVisible(true);
97 | }
98 | }
99 |
100 | public void hideGetFriendRequest() {
101 | if (getFriendRequestFrame != null) {
102 | getFriendRequestFrame.setVisible(false);
103 | }
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/manager/SkinManager.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.manager;
2 |
3 | import iqq.app.core.service.SkinService;
4 | import iqq.app.ui.skin.Skin;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.util.LinkedList;
10 | import java.util.List;
11 |
12 | /**
13 | * 皮肤管理器,可以更新新皮肤
14 | *
15 | * Project : iqq-projects
16 | * Author : 承∮诺 < 6208317@qq.com >
17 | * Created : 14-5-5
18 | * License : Apache License 2.0
19 | */
20 | @Component
21 | public class SkinManager {
22 | private final Logger LOG = LoggerFactory.getLogger(SkinManager.class);
23 | private List skinList = new LinkedList();
24 |
25 | /**
26 | * 注册皮肤管理
27 | *
28 | * @param skin
29 | */
30 | public void register(Skin skin) {
31 | skinList.add(skin);
32 | LOG.debug("register " + skin.getClass().getName());
33 | }
34 |
35 | /**
36 | * 取消注册皮肤管理,放弃持有引用,用来释放对象
37 | *
38 | * @param skin
39 | */
40 | public void unregister(Skin skin) {
41 | skinList.remove(skin);
42 | LOG.debug("unregister " + skin.getClass().getName());
43 | }
44 |
45 | /**
46 | * 安装所有皮肤,更新覆盖原来的
47 | *
48 | * @param skinService
49 | */
50 | public void installAll(SkinService skinService) {
51 | for (Skin skin : skinList) {
52 | skin.installSkin(skinService);
53 | LOG.debug("install " + skin.getClass().getName());
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/BoddyTreeCellRenderer.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer;
2 |
3 | import com.alee.laf.label.WebLabel;
4 | import iqq.app.ui.renderer.node.BuddyNode;
5 | import iqq.app.ui.renderer.node.CategoryNode;
6 |
7 | import javax.swing.*;
8 | import javax.swing.tree.TreeCellRenderer;
9 | import java.awt.*;
10 |
11 | /**
12 | * 好友树中单元显示
13 | *
14 | * Project : iqq-projects
15 | * Author : 承∮诺 < 6208317@qq.com >
16 | * Created : 14-5-8
17 | * License : Apache License 2.0
18 | */
19 | public class BoddyTreeCellRenderer implements TreeCellRenderer {
20 |
21 | @Override
22 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
23 | if (value instanceof CategoryNode) {
24 | CategoryNode cate = (CategoryNode) value;
25 | WebLabel cateLbl = cate.getView();
26 | if (expanded) {
27 | cateLbl.setIcon(UIManager.getIcon("Tree.arrowDown"));
28 | } else {
29 | cateLbl.setIcon(UIManager.getIcon("Tree.arrowLeft"));
30 | }
31 | return cateLbl;
32 | } else if (value instanceof BuddyNode) {
33 | return ((BuddyNode) value).getView();
34 | }
35 | return new WebLabel(value.toString());
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/CategoryComboxCellRenderer.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer;
2 |
3 | import com.alee.laf.label.WebLabel;
4 | import iqq.api.bean.IMCategory;
5 | import iqq.api.bean.IMMsg;
6 | import iqq.app.ui.renderer.node.BuddyNode;
7 | import iqq.app.ui.renderer.node.CategoryNode;
8 | import javax.swing.*;
9 | import java.awt.*;
10 |
11 | public class CategoryComboxCellRenderer extends WebLabel implements ListCellRenderer {
12 |
13 | public CategoryComboxCellRenderer() {
14 | setOpaque(true);
15 | }
16 |
17 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
18 | IMCategory category = (IMCategory) value;
19 | setText(category.getName());
20 | return this;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/RecentTreeCellRenderer.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer;
2 |
3 | import com.alee.laf.label.WebLabel;
4 | import iqq.app.ui.renderer.node.BuddyNode;
5 | import iqq.app.ui.renderer.node.RoomNode;
6 |
7 | import javax.swing.*;
8 | import javax.swing.tree.TreeCellRenderer;
9 | import java.awt.*;
10 |
11 | /**
12 | * 最近列表树中单元显示
13 | *
14 | * Project : iqq-projects
15 | * Author : 承∮诺 < 6208317@qq.com >
16 | * Created : 14-5-9
17 | * License : Apache License 2.0
18 | */
19 | public class RecentTreeCellRenderer implements TreeCellRenderer {
20 | public static int ICON_SIZE = 40;
21 | public static Insets LINE_MARGIN = new Insets(4, 15, 4, 4);
22 |
23 | @Override
24 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
25 | if (value instanceof BuddyNode) {
26 | return ((BuddyNode) value).getView();
27 | } else if (value instanceof RoomNode) {
28 | return ((RoomNode) value).getView(40, 40);
29 | }
30 | return new WebLabel(value.toString());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/RoomTreeCellRenderer.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer;
2 |
3 | import com.alee.laf.label.WebLabel;
4 | import iqq.app.ui.renderer.node.CategoryNode;
5 | import iqq.app.ui.renderer.node.RoomNode;
6 |
7 | import javax.swing.*;
8 | import javax.swing.tree.TreeCellRenderer;
9 | import java.awt.*;
10 |
11 | /**
12 | * 聊天室树中单元显示
13 | *
14 | * Project : iqq-projects
15 | * Author : 承∮诺 < 6208317@qq.com >
16 | * Created : 14-5-9
17 | * License : Apache License 2.0
18 | */
19 | public class RoomTreeCellRenderer implements TreeCellRenderer {
20 | @Override
21 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
22 | if (value instanceof CategoryNode) {
23 | CategoryNode cate = (CategoryNode) value;
24 | WebLabel cateLbl = cate.getView();
25 | if (expanded) {
26 | cateLbl.setIcon(UIManager.getIcon("Tree.arrowDown"));
27 | } else {
28 | cateLbl.setIcon(UIManager.getIcon("Tree.arrowLeft"));
29 | }
30 | return cateLbl;
31 | } else if (value instanceof RoomNode) {
32 | return ((RoomNode) value).getView();
33 | }
34 | return new WebLabel(value.toString());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/node/BuddyNode.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer.node;
2 |
3 | import com.alee.extended.image.WebDecoratedImage;
4 | import com.alee.extended.panel.CenterPanel;
5 | import com.alee.extended.panel.GroupPanel;
6 | import com.alee.laf.label.WebLabel;
7 | import com.alee.utils.ImageUtils;
8 | import iqq.api.bean.IMBuddy;
9 | import iqq.app.ui.IMPanel;
10 | import iqq.app.util.StatusUtils;
11 | import org.apache.commons.lang3.StringUtils;
12 |
13 | import java.awt.*;
14 | import java.awt.image.BufferedImage;
15 |
16 | /**
17 | * 好友显示节点
18 | *
19 | * Project : iqq-projects
20 | * Author : 承∮诺 < 6208317@qq.com >
21 | * Created : 14-5-10
22 | * License : Apache License 2.0
23 | */
24 | public class BuddyNode extends EntityNode {
25 | private IMBuddy buddy;
26 | private IMPanel view = new IMPanel();
27 | // 头像
28 | private BufferedImage avatar;
29 | private WebDecoratedImage avatarImage;
30 | // 昵称
31 | WebLabel nickLbl;
32 | WebLabel signLbl;
33 |
34 | public BuddyNode(IMBuddy buddy) {
35 | super(buddy);
36 | this.buddy = buddy;
37 |
38 | // 头像
39 | avatarImage = new WebDecoratedImage();
40 | avatarImage.setShadeWidth(1);
41 | avatarImage.setRound(4);
42 | avatarImage.setDrawGlassLayer(false);
43 |
44 | // 昵称
45 | nickLbl = new WebLabel();
46 | signLbl = new WebLabel();
47 | nickLbl.setFontSize(14);
48 | signLbl.setFontSize(13);
49 | signLbl.setForeground(Color.GRAY);
50 | GroupPanel textGroup = new GroupPanel(0, false, nickLbl, signLbl);
51 | textGroup.setMargin(0, 5, 0, 5);
52 |
53 | view.add(avatarImage, BorderLayout.WEST);
54 | view.add(new CenterPanel(textGroup, false, true), BorderLayout.CENTER);
55 | view.setMargin(5);
56 | }
57 |
58 | public void setAvatar(BufferedImage avatar) {
59 | this.avatar = avatar;
60 | this.avatarImage.setIcon(ImageUtils.createPreviewIcon(StatusUtils.drawStatusFace(buddy.getStatus(), avatar), 45));
61 | }
62 |
63 | public IMBuddy getBuddy() {
64 | return buddy;
65 | }
66 |
67 | public void setBuddy(IMBuddy buddy) {
68 | this.buddy = buddy;
69 | }
70 |
71 | /**
72 | * 这个方法特别频繁,一定要处理好
73 | *
74 | * @return
75 | */
76 | public IMPanel getView() {
77 | if (avatar == null || avatar != buddy.getAvatarBuffered()) {
78 | setAvatar(buddy.getAvatarBuffered());
79 | }
80 | if (!StringUtils.equals(nickLbl.getText(), buddy.getNick())) {
81 | nickLbl.setText(buddy.getNick());
82 | }
83 | if (!StringUtils.equals(signLbl.getText(), buddy.getSign())) {
84 | signLbl.setText(buddy.getSign());
85 | }
86 | return view;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/node/CategoryNode.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer.node;
2 |
3 | import com.alee.laf.label.WebLabel;
4 | import iqq.api.bean.IMCategory;
5 |
6 | import javax.swing.tree.DefaultMutableTreeNode;
7 |
8 | /**
9 | * 好友分类、聊天室分类显示节点
10 | *
11 | * Project : iqq-projects
12 | * Author : 承∮诺 < 6208317@qq.com >
13 | * Created : 14-5-10
14 | * License : Apache License 2.0
15 | */
16 | public class CategoryNode extends DefaultMutableTreeNode {
17 | private IMCategory category;
18 | private WebLabel view = new WebLabel();
19 |
20 | public CategoryNode(IMCategory category) {
21 | super();
22 | this.category = category;
23 |
24 | view.setMargin(5, 8, 5, 5);
25 | }
26 |
27 | public IMCategory getCategory() {
28 | return category;
29 | }
30 |
31 | public void setCategory(IMCategory category) {
32 | this.category = category;
33 | }
34 |
35 | /**
36 | * 这个方法特别频繁,一定要处理好
37 | *
38 | * @return
39 | */
40 | public WebLabel getView() {
41 | if (!view.getText().equals(category.getName())) {
42 | view.setText(category.getName());
43 | }
44 | return view;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/node/EntityNode.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer.node;
2 |
3 | import iqq.api.bean.IMEntity;
4 |
5 | import javax.swing.tree.DefaultMutableTreeNode;
6 |
7 | /**
8 | * Project : iqq-projects
9 | * Author : 承∮诺 < 6208317@qq.com >
10 | * Created : 14-5-11
11 | * License : Apache License 2.0
12 | */
13 | public class EntityNode extends DefaultMutableTreeNode {
14 | public EntityNode(IMEntity entity) {
15 | super(entity);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/renderer/node/RoomNode.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.renderer.node;
2 |
3 | import com.alee.laf.label.WebLabel;
4 | import com.alee.utils.ImageUtils;
5 | import iqq.api.bean.IMRoom;
6 |
7 | import java.awt.image.BufferedImage;
8 |
9 | /**
10 | * 聊天室显示节点
11 | *
12 | * Project : iqq-projects
13 | * Author : 承∮诺 < 6208317@qq.com >
14 | * Created : 14-5-10
15 | * License : Apache License 2.0
16 | */
17 | public class RoomNode extends EntityNode {
18 | private IMRoom room;
19 | private BufferedImage avatar;
20 | private WebLabel view = new WebLabel();
21 |
22 | public RoomNode(IMRoom room) {
23 | super(room);
24 | this.room = room;
25 |
26 | view.setMargin(5);
27 | }
28 |
29 | public IMRoom getRoom() {
30 | return room;
31 | }
32 |
33 | public void setRoom(IMRoom room) {
34 | this.room = room;
35 | }
36 |
37 | public WebLabel getView() {
38 | return getView(30, 30);
39 | }
40 |
41 | /**
42 | * 这个方法特别频繁,一定要处理好
43 | *
44 | * @return
45 | */
46 | public WebLabel getView(int iconWidth, int iconHeight) {
47 | if (!view.getText().equals(room.getNick())) {
48 | view.setText(room.getNick());
49 | }
50 | if (avatar == null || !avatar.equals(room.getAvatar())) {
51 | avatar = room.getAvatarBuffered();
52 | view.setIcon(ImageUtils.createPreviewIcon(avatar, 43));
53 | }
54 | return view;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/ui/skin/Skin.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui.skin;
2 |
3 | import iqq.app.core.service.SkinService;
4 |
5 | /**
6 | * Project : iqq-projects
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-5-4
9 | * License : Apache License 2.0
10 | */
11 | public interface Skin {
12 | public void installSkin(SkinService skinService);
13 | }
14 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/Benchmark.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * Project : WebQQCore
20 | * Package : iqq.im.util
21 | * File : Benchmark.java
22 | * Author : solosky < solosky772@qq.com >
23 | * Created : 2013-4-7
24 | * License : Apache License 2.0
25 | */
26 | package iqq.app.util;
27 |
28 | import org.slf4j.LoggerFactory;
29 |
30 | import java.util.Date;
31 | import java.util.Deque;
32 | import java.util.LinkedList;
33 |
34 | /**
35 | *
36 | * 一个工具类,可以用来跟踪程序效率问题
37 | * 目前暂时不支持多线程
38 | *
39 | * @author solosky
40 | *
41 | */
42 | public class Benchmark {
43 | private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(Benchmark.class);
44 | private static Deque benchStack = new LinkedList();
45 |
46 |
47 | public static void start(String tag) {
48 | BenchEntry entry = new BenchEntry();
49 | entry.tag = tag;
50 | entry.depth = benchStack.size();
51 | entry.start = new Date();
52 | benchStack.addFirst(entry);
53 | }
54 |
55 | public static void end(String tag) {
56 | BenchEntry entry = benchStack.pollFirst();
57 | if (!entry.tag.equals(tag)) {
58 | LOG.warn("Benchmark Not Match, tag spell mistake or forgot Benchmark.end(tag) invoke at somewhere ??");
59 | return;
60 | }
61 |
62 | entry.end = new Date();
63 | long used = entry.end.getTime() - entry.start.getTime();
64 | LOG.debug("Benchmark [" + entry.tag + " ] - Used: " + (used) + " ms. ");
65 | }
66 |
67 | private static class BenchEntry {
68 | public long depth;
69 | public String tag;
70 | public Date start;
71 | public Date end;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/date/BaseDate.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.date;
2 |
3 | /**
4 | * Created by Tony on 3/28/15.
5 | */
6 | public class BaseDate extends java.util.Date {
7 |
8 | public BaseDate() {
9 | super();
10 | }
11 |
12 | public BaseDate(long milliseconds) {
13 | super(milliseconds);
14 | }
15 |
16 | public BaseDate(java.util.Date date) {
17 | super(date.getTime());
18 | }
19 |
20 | /**
21 | * yyyy-MM-dd
22 | *
23 | * @return
24 | */
25 | public String toDate() {
26 | return Date.formatFor(this);
27 | }
28 |
29 | /**
30 | * yyyy-MM-dd HH:mm:ss
31 | *
32 | * @return
33 | */
34 | public String toDateTime() {
35 | return DateTime.formatFor(this);
36 | }
37 |
38 | /**
39 | * yyyy年MM月dd日
40 | *
41 | * @return
42 | */
43 | public String toDateCN() {
44 | return Date.FORMATTER_CN.format(this);
45 | }
46 |
47 | /**
48 | * yyyy年MM月dd日 HH:mm:ss
49 | *
50 | * @return
51 | */
52 | public String toDateTimeCN() {
53 | return DateTime.FORMATTER_CN.format(this);
54 | }
55 |
56 | /**
57 | * {0}秒之前
58 | * {0}分钟之前
59 | * {0}小时之前
60 | * {0}天之前
61 | * MM月dd日 HH:mm
62 | * yyyy年MM月dd日 HH:mm
63 | *
64 | * @return
65 | */
66 | public String toFriendly() {
67 | return new FriendlyDate(getTime()).toFriendlyDate(true);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/date/Date.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.date;
2 |
3 | import java.text.ParseException;
4 | import java.text.SimpleDateFormat;
5 |
6 | /**
7 | * 日期时间类
8 | * yyyy-MM-dd
9 | *
10 | * Created by Tony on 1/5/15.
11 | */
12 | public class Date extends BaseDate {
13 | public final static SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
14 | public final static SimpleDateFormat FORMATTER_CN = new SimpleDateFormat("yyyy年MM月dd日");
15 |
16 | /**
17 | * string to date
18 | *
19 | * @param string
20 | * @return
21 | */
22 | public static Date parseFor(String string) {
23 | java.util.Date date = null;
24 | try {
25 | date = FORMATTER.parse(string);
26 | } catch (ParseException e) {
27 | e.printStackTrace();
28 | }
29 | return new Date(date);
30 | }
31 |
32 | /**
33 | * date to string
34 | *
35 | * @param date
36 | * @return
37 | */
38 | public static String formatFor(BaseDate date) {
39 | return FORMATTER.format(date);
40 | }
41 |
42 | /**
43 | * 新建一个日期类
44 | *
45 | * @return
46 | */
47 | public static Date newInstance() {
48 | // now to yyyy-MM-dd
49 | String nowDate = FORMATTER.format(new java.util.Date());
50 | try {
51 | return new Date(FORMATTER.parse(nowDate));
52 | } catch (ParseException e) {
53 | e.printStackTrace();
54 | }
55 | return new Date(System.currentTimeMillis());
56 | }
57 |
58 | public Date(long readLong) {
59 | super(readLong);
60 | }
61 |
62 | public Date(java.util.Date date) {
63 | super(date.getTime());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/date/DateTime.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.date;
2 |
3 | import java.text.ParseException;
4 | import java.text.SimpleDateFormat;
5 |
6 | /**
7 | * 日期时间类
8 | * yyyy-MM-dd HH:mm:ss
9 | *
10 | * Created by Tony on 1/5/15.
11 | */
12 | public class DateTime extends BaseDate {
13 | public final static SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
14 | public final static SimpleDateFormat FORMATTER_CN = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
15 |
16 | /**
17 | * string to date
18 | *
19 | * @param string
20 | * @return
21 | */
22 | public static DateTime parseFor(String string) {
23 | java.util.Date date = null;
24 | try {
25 | date = FORMATTER.parse(string);
26 | } catch (ParseException e) {
27 | e.printStackTrace();
28 | }
29 | return new DateTime(date);
30 | }
31 |
32 | /**
33 | * date to string
34 | *
35 | * @param date
36 | * @return
37 | */
38 | public static String formatFor(BaseDate date) {
39 | return FORMATTER.format(date);
40 | }
41 |
42 | /**
43 | * 新建一个日期时间类
44 | *
45 | * @return
46 | */
47 | public static DateTime newInstance() {
48 | // now to yyyy-MM-dd
49 | String nowDate = FORMATTER.format(new java.util.Date());
50 | try {
51 | return new DateTime(FORMATTER.parse(nowDate));
52 | } catch (ParseException e) {
53 | e.printStackTrace();
54 | }
55 | return new DateTime(System.currentTimeMillis());
56 | }
57 |
58 | public DateTime(long readLong) {
59 | super(readLong);
60 | }
61 |
62 | public DateTime(java.util.Date date) {
63 | super(date.getTime());
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/date/DateTimeZone.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.date;
2 |
3 | import java.text.ParseException;
4 | import java.text.SimpleDateFormat;
5 |
6 | /**
7 | * 日期时间类
8 | * yyyy-MM-dd'T'HH:mm:ssZ
9 | *
10 | * Created by Tony on 1/5/15.
11 | */
12 | public class DateTimeZone extends BaseDate {
13 | public final static SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
14 | public final static SimpleDateFormat FORMATTER_CN = new SimpleDateFormat("yyyy年MM月dd日'T'HH:mm:ssZ");
15 |
16 | /**
17 | * string to date
18 | *
19 | * @param string
20 | * @return
21 | */
22 | public static DateTimeZone parseFor(String string) {
23 | java.util.Date date = null;
24 | try {
25 | date = FORMATTER.parse(string);
26 | } catch (ParseException e) {
27 | e.printStackTrace();
28 | }
29 | return new DateTimeZone(date);
30 | }
31 |
32 | /**
33 | * date to string
34 | *
35 | * @param date
36 | * @return
37 | */
38 | public static String formatFor(BaseDate date) {
39 | return FORMATTER.format(date);
40 | }
41 |
42 | /**
43 | * 新建一个日期时间类
44 | *
45 | * @return
46 | */
47 | public static DateTime newInstance() {
48 | // now to yyyy-MM-dd
49 | String nowDate = FORMATTER.format(new java.util.Date());
50 | try {
51 | return new DateTime(FORMATTER.parse(nowDate));
52 | } catch (ParseException e) {
53 | e.printStackTrace();
54 | }
55 | return new DateTime(System.currentTimeMillis());
56 | }
57 |
58 | public DateTimeZone(long readLong) {
59 | super(readLong);
60 | }
61 |
62 | public DateTimeZone(java.util.Date date) {
63 | super(date.getTime());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/gson/DateFormatter.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.gson;
2 |
3 | import com.google.gson.*;
4 | import iqq.app.util.date.Date;
5 | import org.apache.commons.lang3.StringUtils;
6 |
7 | import java.lang.reflect.Type;
8 |
9 | /**
10 | * 日期格式化 yyyy-MM-dd
11 | *
12 | * Created by Tony on 1/5/15.
13 | */
14 | public class DateFormatter implements JsonDeserializer, JsonSerializer {
15 | private static final String TAG = DateFormatter.class.getName();
16 |
17 | /**
18 | * string to date
19 | *
20 | * @param json
21 | * @param typeOfT
22 | * @param context
23 | * @return
24 | * @throws JsonParseException
25 | */
26 | public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
27 | throws JsonParseException {
28 |
29 | String value = json.getAsString();
30 | if (StringUtils.isEmpty(value) || value.length() == 1) {
31 | return null;
32 | }
33 |
34 | return Date.parseFor(value);
35 | }
36 |
37 | /**
38 | * date to string
39 | *
40 | * @param date
41 | * @param type
42 | * @param context
43 | * @return
44 | */
45 | public JsonElement serialize(Date date, Type type, JsonSerializationContext context) {
46 | return new JsonPrimitive(Date.formatFor(date));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/gson/DateTimeFormatter.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.gson;
2 |
3 | import com.google.gson.JsonDeserializationContext;
4 | import com.google.gson.JsonDeserializer;
5 | import com.google.gson.JsonElement;
6 | import com.google.gson.JsonParseException;
7 | import com.google.gson.JsonPrimitive;
8 | import com.google.gson.JsonSerializationContext;
9 | import com.google.gson.JsonSerializer;
10 | import iqq.app.util.date.DateTime;
11 | import org.apache.commons.lang3.StringUtils;
12 |
13 | import java.lang.reflect.Type;
14 |
15 |
16 | /**
17 | * 日期格式化 yyyy-MM-dd
18 | *
19 | * Created by Tony on 1/5/15.
20 | */
21 | public class DateTimeFormatter implements JsonDeserializer, JsonSerializer {
22 | private static final String TAG = DateTimeFormatter.class.getName();
23 |
24 | /**
25 | * string to date
26 | *
27 | * @param json
28 | * @param typeOfT
29 | * @param context
30 | * @return
31 | * @throws JsonParseException
32 | */
33 | public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
34 | throws JsonParseException {
35 |
36 | String value = json.getAsString();
37 | if (StringUtils.isEmpty(value) || value.length() == 1) {
38 | return null;
39 | }
40 |
41 | return DateTime.parseFor(value);
42 | }
43 |
44 | /**
45 | * date to string
46 | *
47 | * @param date
48 | * @param type
49 | * @param context
50 | * @return
51 | */
52 | public JsonElement serialize(DateTime date, Type type, JsonSerializationContext context) {
53 | return new JsonPrimitive(DateTime.formatFor(date));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/main/src/main/java/iqq/app/util/gson/DateTimeZoneFormatter.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util.gson;
2 |
3 | import com.google.gson.*;
4 | import iqq.app.util.date.DateTimeZone;
5 | import org.apache.commons.lang3.StringUtils;
6 |
7 | import java.lang.reflect.Type;
8 |
9 |
10 | /**
11 | * 日期格式化 yyyy-MM-dd
12 | *
13 | * Created by Tony on 1/5/15.
14 | */
15 | public class DateTimeZoneFormatter implements JsonDeserializer, JsonSerializer {
16 | private static final String TAG = DateTimeZoneFormatter.class.getName();
17 |
18 | /**
19 | * string to date
20 | *
21 | * @param json
22 | * @param typeOfT
23 | * @param context
24 | * @return
25 | * @throws JsonParseException
26 | */
27 | public DateTimeZone deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
28 | throws JsonParseException {
29 |
30 | String value = json.getAsString();
31 | if (StringUtils.isEmpty(value) || value.length() == 1) {
32 | return null;
33 | }
34 |
35 | return DateTimeZone.parseFor(value);
36 | }
37 |
38 | /**
39 | * date to string
40 | *
41 | * @param date
42 | * @param type
43 | * @param context
44 | * @return
45 | */
46 | public JsonElement serialize(DateTimeZone date, Type type, JsonSerializationContext context) {
47 | return new JsonPrimitive(DateTimeZone.formatFor(date));
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/main/src/main/resources/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: iqq.app.IMLauncher
3 |
4 |
--------------------------------------------------------------------------------
/main/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [%d{yyyy/MM/dd HH:mm:ss.SSS}][%p][%logger:%L] %m%n
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/main/src/main/resources/spring-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/TestIoc.java:
--------------------------------------------------------------------------------
1 | package iqq.app;
2 |
3 | import iqq.app.core.context.IMContext;
4 | import iqq.app.core.service.SkinService;
5 | import iqq.app.core.service.impl.SkinServiceImpl;
6 | import junit.framework.Assert;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | /**
11 | * Project : iqq
12 | * Author : 承∮诺 < 6208317@qq.com >
13 | * Created : 14-4-16
14 | * License : Apache License 2.0
15 | */
16 | public class TestIoc {
17 | @Before
18 | public void before() {
19 |
20 | }
21 |
22 | @Test
23 | public void testBean() {
24 | SkinService skinService = IMContext.getBean(SkinServiceImpl.class);
25 | Assert.assertNotNull(skinService);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/TestPath.java:
--------------------------------------------------------------------------------
1 | package iqq.app;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * Project : iqq
7 | * Author : 承∮诺 < 6208317@qq.com >
8 | * Created : 14-4-16
9 | * License : Apache License 2.0
10 | */
11 | public class TestPath {
12 | @Test
13 | public void testProjectDir() {
14 | System.out.println(System.getProperty("user.dir"));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/service/TestI18nService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.service;
2 |
3 | import iqq.app.core.context.IMContext;
4 | import iqq.app.core.service.I18nService;
5 | import iqq.app.core.service.impl.I18nServiceImpl;
6 | import org.junit.Assert;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | /**
11 | * Created by Administrator on 2014/4/17.
12 | */
13 | public class TestI18nService {
14 | I18nService i18nService;
15 |
16 | @Before
17 | public void before() {
18 | i18nService = IMContext.getBean(I18nServiceImpl.class);
19 | }
20 |
21 | @Test
22 | public void testDefault() {
23 | //Locale.setDefault(Locale.CANADA);
24 | Assert.assertNotNull(i18nService);
25 | Assert.assertNotNull(i18nService.getMessage("login"));
26 | System.out.println(i18nService.getMessage("conversationTitle", " TEST"));
27 | System.out.println(i18nService.getMessage("login"));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/service/TestResourceService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.service;
2 |
3 | import iqq.app.core.context.IMContext;
4 | import iqq.app.core.service.ResourceService;
5 | import iqq.app.core.service.impl.ResourceServiceImpl;
6 | import junit.framework.Assert;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | import java.io.File;
11 |
12 | /**
13 | * Project : iqq
14 | * Author : 承∮诺 < 6208317@qq.com >
15 | * Created : 14-4-17
16 | * License : Apache License 2.0
17 | */
18 | public class TestResourceService {
19 |
20 | ResourceService resourceService = null;
21 |
22 | @Before
23 | public void before() {
24 | resourceService = IMContext.getBean(ResourceServiceImpl.class);
25 | }
26 |
27 | @Test
28 | public void testResourcesPath() {
29 | String path = resourceService.getResourcePath() + "login/avatar.jpg";
30 | System.out.println(path);
31 | Assert.assertNotNull(path);
32 | Assert.assertTrue(new File(path).exists());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/service/TestSkinService.java:
--------------------------------------------------------------------------------
1 | package iqq.app.service;
2 |
3 | import com.alee.extended.painter.Painter;
4 | import iqq.app.core.service.SkinService;
5 | import iqq.app.core.service.impl.SkinServiceImpl;
6 | import org.junit.Assert;
7 | import org.junit.Test;
8 |
9 | import javax.swing.*;
10 | import java.io.File;
11 |
12 | /**
13 | * Project : iqq
14 | * Author : 承∮诺 < 6208317@qq.com >
15 | * Created : 14-4-16
16 | * License : Apache License 2.0
17 | */
18 | public class TestSkinService {
19 | @Test
20 | public void testPath() {
21 | //System.setProperty("app.dir", "");
22 | SkinService skinService = new SkinServiceImpl();
23 | String path = skinService.getDirectory();
24 | System.out.println(path);
25 | Assert.assertNotNull(path);
26 | Assert.assertTrue(new File(path).exists());
27 | }
28 |
29 | @Test
30 | public void testCustomPath() {
31 | SkinService skinService = new SkinServiceImpl();
32 | String path = skinService.getDirectory();
33 | System.out.println(path);
34 | skinService.setDirectory("skins/test");
35 | skinService.setEnableCustom(false);
36 | }
37 |
38 | @Test
39 | public void testColor() {
40 | SkinService skinService = new SkinServiceImpl();
41 |
42 | System.out.println(skinService.getColorByKey("window/titleColor1"));
43 | }
44 |
45 | @Test
46 | public void tesIcon() {
47 | SkinService skinService = new SkinServiceImpl();
48 | Assert.assertTrue(skinService.getIconByKey("window/titleIcon") instanceof ImageIcon);
49 | Assert.assertTrue(skinService.getPainterByKey("login/background") instanceof Painter);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/ui/TestLogin.java:
--------------------------------------------------------------------------------
1 | package iqq.app.ui;
2 |
3 | import com.alee.laf.WebLookAndFeel;
4 | import iqq.app.ui.frame.LoginFrame;
5 | import iqq.app.ui.frame.VerifyFrame;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | import java.util.Scanner;
10 |
11 | /**
12 | * Project : iqq
13 | * Author : 承∮诺 < 6208317@qq.com >
14 | * Created : 14-4-16
15 | * License : Apache License 2.0
16 | */
17 | public class TestLogin {
18 |
19 | @Before
20 | public void before() {
21 | WebLookAndFeel.install();
22 | }
23 |
24 | @Test
25 | public void testLoginBg() {
26 | LoginFrame login = new LoginFrame();
27 | new Scanner(System.in).next();
28 | }
29 |
30 | @Test
31 | public void testVerification() {
32 | VerifyFrame ver = new VerifyFrame();
33 | ver.setVisible(true);
34 | new Scanner(System.in).next();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/main/src/test/java/iqq/app/util/TestXml.java:
--------------------------------------------------------------------------------
1 | package iqq.app.util;
2 |
3 | import org.dom4j.Document;
4 | import org.dom4j.DocumentException;
5 | import org.dom4j.DocumentHelper;
6 | import org.dom4j.Element;
7 | import org.junit.Assert;
8 | import org.junit.Test;
9 |
10 | import java.io.IOException;
11 |
12 | /**
13 | * Project : iqq
14 | * Author : 承∮诺 < 6208317@qq.com >
15 | * Created : 14-4-16
16 | * License : Apache License 2.0
17 | */
18 | public class TestXml {
19 |
20 | @Test
21 | public void testWrite() {
22 | String xmlFile = System.getProperty("user.dir") + "/config.xml";
23 | Document doc = DocumentHelper.createDocument();
24 |
25 | Element root = doc.addElement("roots");
26 | root.addElement("test").setText("test123");
27 |
28 | Element element = root.addElement("iqq");
29 | element.addElement("version").setText("iqqv3");
30 |
31 | // 测试XmlUtils
32 | try {
33 | XmlUtils.writeXml(xmlFile, doc);
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | @Test
40 | public void testRead() {
41 | String xmlFile = System.getProperty("user.dir") + "/config.xml";
42 | try {
43 | String text = XmlUtils.getNodeText(xmlFile, "iqq/version");
44 | System.out.println(text);
45 | Assert.assertNotNull(text);
46 | } catch (DocumentException e) {
47 | e.printStackTrace();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/resources/i18n/appBundle.properties:
--------------------------------------------------------------------------------
1 | #login
2 | login.account = Account
3 | login.password = Password
4 | login.login = Login
5 | login.forgetPwd=Forget Password
6 | login.rememberPwd=Remember Password
7 | login.regAccount=Register
8 | login.cancel = Cancel
9 | login.inputUsername = Please enter a username!
10 | login.inputPassword = Please enter your password!
11 | login.netError = Unable to connect to Q+ Server, please check your connection and try again!
12 | login.failed = Login Failed!
13 |
14 | veriry.verify=Verify
15 | veriry.reset=Verify Reset
16 | verify.freshVerifyFailed = Fresh verify image failed! Retry it ?
17 |
18 | #main panel
19 | contacts = Contacts
20 | groups = Groups
21 | recently =Recent
22 | setting=Setting
23 | confirm=OK
24 | cancel = Cancel
25 | app.name=IQQ
26 | app.skinSetting=Skin Settings
27 |
28 | status.online=Online
29 | status.callme=Callme
30 | status.away=Away
31 | status.meeting=Meeting
32 | status.silent=Silent
33 | status.hidden=Hidden
34 | status.offline=Offline
35 | findContact=Find a contact...
36 | minimize=Minimize
37 | maximize=Maximize
38 | close=Close
39 | myDiscuz=My Discuz
40 | myGroup=My Group
41 | conversationTitle= Conversation With {0}
42 | sendMsgEmpty=The message cannot be empty. Please enter again.
43 | chat.text=Font
44 | chat.emoticon=Emoticon
45 | chat.screenCapture=ScreenCapture
46 | chat.shake=Shake
47 | chat.pictures=Pictures
48 | chat.history=History
49 | chat.send=Send Message
50 | chat.picNotSupported = Current version is not supported send group or discuz picture for Q+ protocol limit.
51 | chat.recvShake = contact has sent a shake message.
52 | chat.sendShake = you have sent a shake message.
53 | chat.msg.read = Read
54 | chat.picLengthNotSupported=The pictures filesize exceeds the limit of 1MB.
55 | chat.msg.unread = Unread
56 | chat.msg.pending = Pending..
57 | chat.msg.error = Send Failed..
58 | chat.msg.sent = Sent
59 | chat.userInputting = Writing..
60 | userView=User View
61 | groupView=Group View
62 | conversationView=Conversation View
63 | bigFace=Big Face
64 | smallFace=Small Face
65 | chat.setting=Setting
66 | customFace=Custom Face
67 | normalFace=Normal Face
68 | chat.fileTransfer=File Transfer
69 | chat.showMembers=Show Members
70 | netOffline=You are offline because of a connection problem.
71 | chat.selfOffline=You are offline now.
72 |
73 | user.gender=Gender
74 | user.age=Age
75 | user.country=Country
76 | user.province=Province
77 | user.occupation=Occupation
78 | user.level=Level
79 | user.clientType=Client Type
80 | user.email=Email
81 | user.male=Male
82 | user.female=Female
83 |
--------------------------------------------------------------------------------
/resources/i18n/appBundle_zh_CN.properties:
--------------------------------------------------------------------------------
1 | #login
2 | login.account = \u8D26\u53F7
3 | login.password = \u5BC6\u7801
4 | login.rememberPwd=\u8BB0\u4F4F\u5BC6\u7801
5 | login.regAccount=\u6CE8\u518C\u8D26\u53F7
6 | login.forgetPwd=\u5FD8\u8BB0\u5BC6\u7801
7 | login.login = \u767B\u5F55
8 | login.cancel = \u53D6\u6D88
9 | login.inputUsername = \u8BF7\u8F93\u5165\u8D26\u53F7\u3002
10 | login.inputPassword = \u8BF7\u8F93\u5165\u5BC6\u7801\u3002
11 | login.netError = \u65E0\u6CD5\u8FDE\u63A5Q+\u670D\u52A1\u5668\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5\u7136\u540E\u91CD\u8BD5\u3002
12 | login.failed = \u767B\u5F55\u5931\u8D25\uFF01
13 |
14 | veriry.verify=\u9A8C\u8BC1\u7801
15 | veriry.reset=\u770B\u4E0D\u6E05\u695A\uFF0C\u6362\u4E00\u5F20\u3002
16 | verify.freshVerifyFailed = \u5237\u65B0\u9A8C\u8BC1\u7801\u5931\u8D25\uFF0C\u662F\u5426\u91CD\u8BD5\uFF1F
17 |
18 | sendMsgEmpty=\u53D1\u9001\u7684\u6D88\u606F\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165\u3002
19 | userView=\u7528\u6237\u663E\u793A
20 | groupView=\u7FA4\u7EC4\u663E\u793A
21 | conversationView=\u4F1A\u8BDD\u663E\u793A
22 | setting=\u8BBE\u7F6E
23 | bigFace=\u5927\u5934\u50CF
24 | smallFace=\u5C0F\u5934\u50CF
25 | customFace=\u81EA\u5B9A\u4E49\u5934\u50CF
26 | normalFace=\u4E2D\u5934\u50CF
27 |
28 | #main panel
29 | contacts = \u8054\u7CFB\u4EBA
30 | groups = \u7FA4\u4E0E\u8BA8\u8BBA\u7EC4
31 | recently =\u6700\u8FD1\u8054\u7CFB
32 | app.name=IQQ
33 | minimize=\u6700\u5C0F\u5316
34 | maximize=\u6700\u5927\u5316
35 | close=\u5173\u95ED
36 | confirm=\u786E\u5B9A
37 | cancel = \u53D6\u6D88
38 | myGroup=\u6211\u7684QQ\u7FA4
39 | myDiscuz=\u6211\u7684\u8BA8\u8BBA\u7EC4
40 | status.online=\u5728\u7EBF
41 | status.callme=Q\u6211\u5427
42 | status.away=\u79BB\u5F00
43 | status.meeting=\u5FD9\u788C
44 | status.silent=\u8BF7\u52FF\u6253\u6270
45 | status.hidden=\u9690\u8EAB
46 | status.offline=\u79BB\u7EBF
47 | findContact=\u641C\u7D22\uFF1A\u8054\u7CFB\u4EBA...
48 | conversationTitle=\u4E0E {0} \u7684\u5BF9\u8BDD
49 | chat.text=\u5B57\u4F53
50 | chat.emoticon=\u8868\u60C5
51 | chat.screenCapture=\u622A\u56FE
52 | chat.shake=\u9707\u52A8
53 | chat.pictures=\u56FE\u7247
54 | chat.history=\u5386\u53F2\u8BB0\u5F55
55 | chat.send=\u53D1\u9001\u6D88\u606F
56 | chat.msg.read = \u5DF2\u8BFB
57 | chat.msg.unread = \u672A\u8BFB
58 | chat.setting=\u8BBE\u7F6E
59 | chat.msg.pending = \u7B49\u5F85\u53D1\u9001..
60 | chat.msg.error = \u53D1\u9001\u5931\u8D25..
61 | chat.msg.sent = \u5DF2\u53D1\u9001
62 | chat.picNotSupported=\u62B1\u6B49\uFF0C\u7531\u4E8EQ+\u534F\u8BAE\u9650\u5236\uFF0C\u5F53\u524D\u7248\u672C\u4E0D\u652F\u6301\u53D1\u9001\u7FA4\u6216\u8BA8\u8BBA\u7EC4\u56FE\u7247\u3002
63 | chat.picLengthNotSupported=\u62B1\u6B49\uFF0C\u7531\u4E8EQ+\u534F\u8BAE\u9650\u5236\uFF0C\u53D1\u9001\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC71MB\u5927\u5C0F\u3002
64 | chat.recvShake = \u5BF9\u65B9\u7ED9\u60A8\u53D1\u9001\u4E86\u4E00\u4E2A\u7A97\u53E3\u6296\u52A8\u3002
65 | chat.sendShake =\u60A8\u7ED9\u5BF9\u65B9\u53D1\u9001\u4E86\u4E00\u4E2A\u7A97\u53E3\u6296\u52A8\u3002
66 | chat.fileTransfer=\u6587\u4EF6\u4F20\u8F93
67 | chat.showMembers=\u663E\u793A\u6210\u5458
68 | chat.userInputting=\u6B63\u5728\u8F93\u5165..
69 | netOffline = \u7531\u4E8E\u7F51\u7EDC\u539F\u56E0\uFF0C\u60A8\u5DF2\u7ECF\u79BB\u7EBF\u3002
70 | chat.selfOffline = \u60A8\u5DF2\u7ECF\u79BB\u7EBF\u3002
71 |
72 | user.gender=\u6027\u522B
73 | user.age=\u5E74\u9F84
74 | user.country=\u56FD\u5BB6
75 | user.province=\u7701
76 | user.occupation=\u804C\u4E1A
77 | user.email=\u90AE\u7BB1
78 | user.level=\u7B49\u7EA7
79 | user.clientType=\u5BA2\u6237\u7AEF\u7C7B\u578B
80 | user.male=\u7537
81 | user.female=\u5973
82 | app.skinSetting=\u76AE\u80A4\u8BBE\u7F6E
83 |
--------------------------------------------------------------------------------
/resources/icons/default/qq_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/default/qq_icon.png
--------------------------------------------------------------------------------
/resources/icons/login/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/avatar.jpg
--------------------------------------------------------------------------------
/resources/icons/login/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/avatar.png
--------------------------------------------------------------------------------
/resources/icons/login/avatar2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/avatar2.png
--------------------------------------------------------------------------------
/resources/icons/login/captcha.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/captcha.jpg
--------------------------------------------------------------------------------
/resources/icons/login/face.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/face.jpg
--------------------------------------------------------------------------------
/resources/icons/login/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/group.png
--------------------------------------------------------------------------------
/resources/icons/login/qq_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/login/qq_icon.png
--------------------------------------------------------------------------------
/resources/icons/status/away.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/away.png
--------------------------------------------------------------------------------
/resources/icons/status/callme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/callme.png
--------------------------------------------------------------------------------
/resources/icons/status/hidden.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/hidden.png
--------------------------------------------------------------------------------
/resources/icons/status/meeting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/meeting.png
--------------------------------------------------------------------------------
/resources/icons/status/offline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/offline.png
--------------------------------------------------------------------------------
/resources/icons/status/online.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/online.png
--------------------------------------------------------------------------------
/resources/icons/status/silent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/icons/status/silent.png
--------------------------------------------------------------------------------
/resources/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | iqq.app
9 | iqq
10 | 3.0.0-SNAPSHOT
11 |
12 |
13 | iqq-resources
14 | jar
15 | iqq资源文件模块
16 |
17 |
18 |
--------------------------------------------------------------------------------
/resources/screenshots/chat-msg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/screenshots/chat-msg.png
--------------------------------------------------------------------------------
/resources/screenshots/chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/screenshots/chat.png
--------------------------------------------------------------------------------
/resources/screenshots/main-skin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/screenshots/main-skin.png
--------------------------------------------------------------------------------
/resources/screenshots/main-skin2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/screenshots/main-skin2.png
--------------------------------------------------------------------------------
/resources/screenshots/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/resources/screenshots/main.png
--------------------------------------------------------------------------------
/skin-default/chat/bg/balloon/balloon_left_blue.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/bg/balloon/balloon_left_blue.9.png
--------------------------------------------------------------------------------
/skin-default/chat/bg/balloon/balloon_left_green.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/bg/balloon/balloon_left_green.9.png
--------------------------------------------------------------------------------
/skin-default/chat/bg/balloon/balloon_left_white.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/bg/balloon/balloon_left_white.9.png
--------------------------------------------------------------------------------
/skin-default/chat/bg/balloon/balloon_right_blue.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/bg/balloon/balloon_right_blue.9.png
--------------------------------------------------------------------------------
/skin-default/chat/bg/balloon/balloon_right_grey.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/bg/balloon/balloon_right_grey.9.png
--------------------------------------------------------------------------------
/skin-default/chat/bg/nav_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/bg/nav_bg.9.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/emoticon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/emoticon.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/fileTransfere.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/fileTransfere.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/history.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/noMessage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/noMessage.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/offMessage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/offMessage.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/pictures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/pictures.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/screenCapture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/screenCapture.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/send.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/send.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/shake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/shake.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/inputbar/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/inputbar/text.png
--------------------------------------------------------------------------------
/skin-default/chat/icons/setting_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/chat/icons/setting_icon.png
--------------------------------------------------------------------------------
/skin-default/font/wqy-microhei.ttc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/font/wqy-microhei.ttc
--------------------------------------------------------------------------------
/skin-default/login/bg/footer_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/login/bg/footer_bg.9.png
--------------------------------------------------------------------------------
/skin-default/login/bg/login_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/login/bg/login_bg.9.png
--------------------------------------------------------------------------------
/skin-default/login/bg/login_bg2.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/login/bg/login_bg2.9.png
--------------------------------------------------------------------------------
/skin-default/login/icons/key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/login/icons/key.png
--------------------------------------------------------------------------------
/skin-default/login/icons/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/login/icons/setting.png
--------------------------------------------------------------------------------
/skin-default/login/icons/setting_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/login/icons/setting_active.png
--------------------------------------------------------------------------------
/skin-default/main/bg/search_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/bg/search_bg.9.png
--------------------------------------------------------------------------------
/skin-default/main/bg/tab_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/bg/tab_bg.9.png
--------------------------------------------------------------------------------
/skin-default/main/icons/arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/arrow_down.png
--------------------------------------------------------------------------------
/skin-default/main/icons/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/arrow_left.png
--------------------------------------------------------------------------------
/skin-default/main/icons/search_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/search_icon.png
--------------------------------------------------------------------------------
/skin-default/main/icons/tab_boddy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/tab_boddy.png
--------------------------------------------------------------------------------
/skin-default/main/icons/tab_group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/tab_group.png
--------------------------------------------------------------------------------
/skin-default/main/icons/tab_recent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/tab_recent.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/add.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/mail.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/msg_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/msg_new.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/msg_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/msg_normal.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/msgrecode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/msgrecode.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/qzone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/qzone.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/setting.png
--------------------------------------------------------------------------------
/skin-default/main/icons/toolbar/weibo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/main/icons/toolbar/weibo.png
--------------------------------------------------------------------------------
/skin-default/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | iqq.app
9 | iqq
10 | 3.0.0-SNAPSHOT
11 |
12 |
13 | iqq-skins
14 | jar
15 | iqq默认皮肤资源模块
16 |
17 |
--------------------------------------------------------------------------------
/skin-default/skin/bg/0.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/0.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/1.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/1.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/10.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/10.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/11.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/11.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/12.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/12.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/13.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/13.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/14.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/14.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/2.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/2.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/3.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/3.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/4.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/4.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/5.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/5.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/6.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/6.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/7.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/7.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/8.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/8.9.png
--------------------------------------------------------------------------------
/skin-default/skin/bg/9.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/bg/9.9.png
--------------------------------------------------------------------------------
/skin-default/skin/icons/skin_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/skin/icons/skin_icon.png
--------------------------------------------------------------------------------
/skin-default/window/bg/transparent.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/bg/transparent.9.png
--------------------------------------------------------------------------------
/skin-default/window/bg/window_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/bg/window_bg.9.png
--------------------------------------------------------------------------------
/skin-default/window/icons/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/close.png
--------------------------------------------------------------------------------
/skin-default/window/icons/close_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/close_active.png
--------------------------------------------------------------------------------
/skin-default/window/icons/maximize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/maximize.png
--------------------------------------------------------------------------------
/skin-default/window/icons/maximize_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/maximize_active.png
--------------------------------------------------------------------------------
/skin-default/window/icons/minimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/minimize.png
--------------------------------------------------------------------------------
/skin-default/window/icons/minimize_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/minimize_active.png
--------------------------------------------------------------------------------
/skin-default/window/icons/restore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/restore.png
--------------------------------------------------------------------------------
/skin-default/window/icons/restore_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/restore_active.png
--------------------------------------------------------------------------------
/skin-default/window/icons/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/setting.png
--------------------------------------------------------------------------------
/skin-default/window/icons/setting_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/setting_active.png
--------------------------------------------------------------------------------
/skin-default/window/icons/skin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/skin.png
--------------------------------------------------------------------------------
/skin-default/window/icons/skin_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/skin_active.png
--------------------------------------------------------------------------------
/skin-default/window/icons/title_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/title_icon.png
--------------------------------------------------------------------------------
/skin-default/window/icons/title_w_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/title_w_icon.png
--------------------------------------------------------------------------------
/skin-default/window/icons/title_w_icon_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonybase/italk/78a6f41809d1eabf4235c7e7c66f447d931d7d71/skin-default/window/icons/title_w_icon_black.png
--------------------------------------------------------------------------------