精彩的人生

好好工作,好好生活

BlogJava 首页 新随笔 联系 聚合 管理
  147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

#

原文地址:http://www.duduwolf.com/post/chatroom_for_AJAX.asp


Aether之邀写一个基础点的AJAX操作实例,想来想去就写一个聊天室吧,以前写AJAX时一来偷懒,二来为了简单,都用纯文本或者javascript数组进行交互,这次改成纯粹的xml操作。想得时候很简单,无非就处理发送消息,接收消息,登陆和退出这几种事件,但真正要写的时候还是颇费周折,主要是ASP对Session间的消息(对象)传递功能太弱了,只能在Application、数据库、自定义服务端组件三种方法中挑一个,自定义服务端组件先Pass了,既然要写一个轻量级的,数据库能不用就不用了,最后还是盯上了Application。

聊天室最重要的功能就是一个用户发出消息后所有用户都要能接收到,接受到消息后应该给这则消息一个标记或者删除操作。ASP的Application对象可以实现Session间的数据交互,再结合类似于Map的Scripting.Dictionary这个内置对象,应该就能实现我想要的效果。但是在实际编写过程中发现Scripting.Dictionary对象实例根本无法存储到Application中,查了MSDN后才知不允许将OBJECT和自定义组件以外的对象存储到Application中,包括自定义Class,晕,只得另想办法,最后选定用数组方式解决。

客户端我用javascript的prototype(原型)功能写了一个ChatRoom类,用面向对象的方式实现了发送接收消息,登录和退出。下面就是聊天窗口,请输入昵称登录后就能开始聊天了:)程序还有很多bug,实在无心调试了。

下载:http://www.duduwolf.com/test/chatRoom.asp.txt

<script language="javascript" type="text/javascript" src="http://www.duduwolf.com/test/chatRoom.asp?act=script"></script>
<div id="chatRoom"></div>
<script>var chat = new ChatRoom('chat', document.getElementById('chatRoom'), 500, 400);</script>

posted @ 2006-01-20 11:57 hopeshared 阅读(527) | 评论 (0)编辑 收藏

前言

这三天来,一直在为一个问题所困扰。

我做的项目是将emf和gef结合的一个典型实例。其实我接触这些东西也才4,5个月,两个Eclipse工具都很熟悉,但是并不能说是精通。

在项目制作的过程中,编辑器的布局问题并没有拿到桌面上来讨论。毕竟,功能没有实现,编辑器作的再漂亮也不起作用。

现在,所有的功能点全部按要求实现了,可是再看看编辑器,就会觉得很外行,呵呵。

尽管老大不在公司,但是我想他肯定支持我的这个想法:将界面作的professional一点。

于是,我浪费了3天时间来重新做布局。



搜索icon

项目组没有给我配备美工,所有的图片都是临时的,我就采用了一些qq表情图,所以编辑器很“可爱”。现在需要根据每个模型的实际含义来配备icon,于是利用google & baidu搜了一些图片下来。好在我还会点ps,那二十多个图标就算定了。


研究布局

这次的代码大改造,需要严重的感谢一个人:reload_cn。非常感谢他能耐心的听我不停的发牢骚,并给于正确的指导。这对后来的改造成功起决定性作用。尽管他将社区里的帅照改成了黑猩猩......

好,转入正题。目前的编辑器功能已经实现了,但是为什么要改布局呢?因为现在编辑器采用的是xyLayout,创建一个对象之后,将它的xywh保存在模型对象中,然后再refreshVisual的时候设置Figure的Bound。这么做的问题是,首先,没有很好的计算坐标,所以坐标有点出入(有的时候坐标出入大的难以接受),其次,本工具定义的主要是流程,所以编辑器里的“内容”很多,每创建一个对象都需要手工拖拽到合适的位置上。

在reload_cn的提示下,我研究了一下GEF的Flow例子。由于时间关系(元旦之后就会发布最终版本,要不加班,要不加快脚步干活),我直接就将flow里的GraphLayoutManager拿过来用了...

结果是,经常报些莫名其妙的错误。

所谓心急吃不了热豆腐。

继续在reload_cn的提示下,研究了他的sequnce diagram的例子。在这个例子中,他做了个很简单的布局处理。

从这里例子中,我领悟出了真谛:
      在EditPart中设置的Layout Policy其实主要处理的是创建对象等等request,并不处理真正的编辑器布局。又或者说它的布局是逻辑意义上的。真正处理布局,来让我们看到效果的,是Figure的布局。而这个正好是我常常忽略的。

Figure怎么布局??我一般用的就是xyLayout和ToolbarLayout。但是如果要作出漂亮的效果,这些还是不够的。八进制的blog中提到了draw2d的tree example。我看过了,然后研究了一下,觉得太简单了,不能符合本项目的需求。

回头再看看flow,觉得这个例子本身就是流程定义,并且跟我的项目在Figure上有很多共同点。。。

仍然心有余悸,毕竟用flow的代码作的所有尝试(用了1天的时间)全部失败了,而且还败的莫名其妙。


开始尝试

不能因为失败,所以放弃(但是可以有放弃的想法,呵呵)。我决定一点一点地来尝试。

首先,我替换了所有的icon,至少图标看起来已经舒服多了。

接着,根据flow中figure的做法,更新了项目中的所有Figure。运行一下看看,呵呵,至少图标很象了。

我很喜欢flow中自动计算Figure位置的功能和动态移动效果。怎么办?继续改装代码。

将GraphLayoutManager小心翼翼的搬了过来。没有效果。但是至少没有出错。

开始使用GraphLayoutManager来进行坐标计算。(这个过程漫长而痛苦,不停的报异常,不停的对比代码,不停的跟踪,不停的发牢骚....)

最后出的问题最有意思,假如编辑器根模型的Figure采用flow中的figure,那么编辑器中只显示连线。为什么呢?因为我的编辑器中使用的是viewer.setRootEditPart(new ScalableFreeformRootEditPart());而flow中用的是getGraphicalViewer().setRootEditPart(new ScalableRootEditPart());所以在我这边,figure采用FreeformLayer就no problem了。

最终得结果是改好了,一切都跟flow那么象

结果

1.GIF     2.GIF


结论

假如你和我一样,在项目制作后期修改编辑器的布局,这里有几个建议:

1 研究一下例子,从简单的开始,一直到难的,让理论知识根深蒂固。
2 作个小例子,或者将你已经作的小例子进行类似的改编,看看出什么问题,为什么出问题。
3 例子没做出来没关系,这些跟头栽在小例子上比栽在项目中让人欣慰的多。
4 先修改Figure。尽量接近你想要的效果。
5 引入布局,暂时不要使用它,只要他的流程走下来没有问题就成功了一半。
6 使用布局。会出现很多问题,但是很容易定位问题。调试吧。

暂时就这么多吧,刚刚的改动导致了编辑器中的删除功能抛异常,我得看看去

posted @ 2005-12-30 14:58 hopeshared 阅读(1973) | 评论 (8)编辑 收藏

两天前GEF发布了3.1M7版本,但使用下来发现和M6没有什么区别,是不是主要为了和Eclipse版本相配套?希望3.1正式版早日发布,应该会新增不少内容。上一篇帖子介绍了如何实现表格功能,在开发过程中,另一个经常用到的功能就是树,虽然SWT提供了标准的树控件,但使用它完成如组织结构图这样的应用还是不够直观和方便。在目前版本(3.1M7)的GEF中虽然没有直接支持树的实现,但Draw2D提供的例子程序里却有我们可以利用的代码(org.eclipse.draw2d.examples.tree.TreeExample,运行界面见下图),通过它可以节约不少工作量。

treeexample.gif
图1 Draw2D例子中的TreeExample

记得数年前曾用Swing做过一个组织结构图的编辑工具,当时的实现方式是让画布使用XYLayout,在适当的时候计算和刷新每个树节点的位置,算法的思想则是深度优先搜索,非树叶节点的位置由其子节点的数目和位置决定。我想这应该是比较直观的方法吧,但是这次看了Draw2D例子里的实现觉得也很有道理,以前没想到过。在这个例子里树节点图形称为TreeBranch,它包含一个PageNode(表现为带有折角的矩形)和一个透明容器contentsPane,(一个Layer,用来放置子节点)。在一般情况下,TreeBranch本身使用名为NormalLayout的布局管理器将PageNode放在子节点的正上方,而contentsPane则使用名为TreeLayout的布局管理器计算每个子节点应在的位置。所以我们看到的整个树实际上是由很多层子树叠加而成的,任何一个非叶节点对应的图形的尺寸都等于以它为根节点的子树所占区域的大小。

从这个例子里我们还看到,用户可以选择使用横向或纵向组织树(见图2),可以压缩各节点之间的空隙,每个节点可以横向或纵向排列子节点,还可以展开或收起子节点,等等,这为我们实现一个方便好用的树编辑器提供了良好的基础(视图部分的工作大大简化了)。

treevertical.gif
图2 纵向组织的树

这里要插一句,Draw2D例子中提供的这些类的具体内容我没有仔细研究,相当于把它们当作Draw2D API的一部分来用了(包括TreeRoot、TreeBranch、TreeLayout、BranchLayout、NormalLayout、HangingLayout、PageNode等几个类,把代码拷到你的项目中即可使用),因为按照GEF 3.1的计划表,它们很有可能以某种形式出现在正式版的GEF 3.1里。下面介绍一下我是如何把它们转换为GEF应用程序的视图部分从而实现树编辑器的。

首先从模型部分开始。因为树是由一个个节点构成的,所以模型中最主要的就是节点类(我称为TreeNode),它和例子里的TreeBranch图形相对应,它应该至少包含nodes(子节点列表)和text(显示文本)这两个属性;例子里有一个TreeRoot是TreeBranch的子类,用来表示根节点,在TreeRoot里多了一些属性,如horizontal、majorSpacing等等用来控制整个树的外观,所以模型里也应该有一个继承TreeNode的子类,而实际上这个类就应该是编辑器的contents,它对应的图形TreeRoot也就是一般GEF应用程序里的画布,这个地方要想想清楚。同时,虽然看起来节点间有线连接,但这里我们并不需要Connection对象,这些线是由布局管理器绘制的,毕竟我们并不需要手动改变线的走向。所以,模型部分就是这么简单,当然别忘了要实现通知机制,下面看看都有哪些EditPart。

与模型相对应,我们有TreeNodePart和TreeRootPart,后者和前者之间也是继承关系。在getContentPane()方法里,要返回TreeBranch图形所包含的contentsPane部分;在getModelChildren()方法里,要返回TreeNode的nodes属性;在createFigure()方法里,TreeNodePart应返回TreeBranch实例,而TreeRootPart要覆盖这个方法,返回TreeRoot实例;另外要注意在refreshVisuals()方法里,要把模型的当前属性正确反映到图形中,例如TreeNode里有反映节点当前是否展开的布尔变量expanded,则refreshVisuals()方法里一定要把这个属性的当前值赋给图形才可以。以下是TreeNodePart的部分代码:

public IFigure getContentPane() {
    
return ((TreeBranch) getFigure()).getContentsPane();
}


protected List getModelChildren() {
    
return ((TreeNode) getModel()).getNodes();
}


protected IFigure createFigure() {
    
return new TreeBranch();
}


protected void createEditPolicies() {
    installEditPolicy(EditPolicy.COMPONENT_ROLE, 
new TreeNodeEditPolicy());
    installEditPolicy(EditPolicy.LAYOUT_ROLE, 
new TreeNodeLayoutEditPolicy());
    installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, 
new ContainerHighlightEditPolicy());
}

上面代码中用到了几个EditPolicy,这里说一下它们各自的用途。实际上,从Role中已经可以看出来,TreeNodeEditPolicy是用来负责节点的删除,没有什么特别;TreeNodeLayoutEditPolicy则复杂一些,我把它实现为ConstrainedLayoutEditPolicy的一个子类,并实现createAddCommand()和getCreateCommand()方法,分别返回改变节点的父节点和创建新节点的命令,另外我让createChildEditPolicy()方法返回NonResizableEditPolicy的实例,并覆盖其createSelectionHandles()方法如下,以便在用户选中一个节点时用一个控制点表示选中状态,不用缺省边框的原因是,边框会将整个子树包住,不够美观,并且在多选的时候界面比较混乱。

protected List createSelectionHandles() {
    List list
=new ArrayList();
    list.add(
new ResizeHandle((GraphicalEditPart)getHost(), PositionConstants.NORTH));
    
return list;
}

选中节点的效果如下图,我根据需要改变了树节点的显示(修改PageNode类):

treeselection.gif
图3 同时选中三个节点(Node2、Node3和Node8)

最后一个ContainerHighlightEditPolicy的唯一作用是当用户拖动节点到另一个节点区域中时,加亮显示后者,方便用户做出是否应该放开鼠标的选择。它是GraphicalEditPolicy的子类,部分代码如下,如果你看过Logic例子的话,应该不难发现这个类就是我从那里拿过来然后修改一下得到的。

protected void showHighlight() {
    ((TreeBranch) getContainerFigure()).setSelected(
true);
}


public void eraseTargetFeedback(Request request) {
    ((TreeBranch) getContainerFigure()).setSelected(
false);
}

好了,现在树编辑器应该已经能够工作了。为了让用户使用更方便,你可以实现展开/收起子节点、横向/纵向排列子节点等等功能,在视图部分Draw2D的例子代码已经内置了这些功能,你要做的就是给模型增加适当的属性。我这里的一个截图如下所示,其中Node1是收起状态,Node6纵向排列子节点(以节省横向空间)。

treeeditor.gif
图4 树编辑器的运行界面

这个编辑器我花一天时间就完成了,但如果不是利用Draw2D的例子,相信至少要四至六天,而且缺陷会比较多,功能上也不会这么完善。我感觉在GEF中遇到没有实现过的功能前最好先找一找有没有可以利用的资源,比如GEF提供的几个例子就很好,当然首先要理解它们才谈得上利用。


原文地址: http://bjzhanghao.cnblogs.com/archive/2005/05/27/163277.html

posted @ 2005-12-28 16:55 hopeshared 阅读(524) | 评论 (0)编辑 收藏

在使用GEF进行开发的时候,对于需要绘制的图形的节点,往往除了模型对象本身之外,还需要有一个相应的“图”对象来保存图中这个节点的位置,以及大小等图相关,但是与业务模型无关的一个对象。而在一开始希望显示一个初始模型文件的时候,再对应保存图信息的文件不存在的情况下,如何能够很好的显示这个图,是一个比较麻烦的问题,涉及到对布局算法的一些分析与实现。这片文章就是介绍,如何使用GEF内的DirectedGraph这个类以及其相应的布局算法类DirectedGraphLayout,来解决这个问题。
基本思想是:为
GEFEditPart模型生成一个DirectedGraph,然后使用DirectedGraphLayout来计算布局,最后将布局的结果通过GEF显示出来。

 

在参考了GEFflow example之后,对其代码作了部分重构,写了这片文章,希望对遇到同样问题的同志能够有一定的帮助。

 

首先引入一个接口:

public interface GraphBuilder {

       public void contributeNodesToGraph(DirectedGraph graph, Map map);

       public void contributeEdgesToGraph(DirectedGraph graph, Map map);

       public void applyGraphResults(DirectedGraph graph, Map map);

}

这个接口中定义了几个方法,其含义从其方法名中可以猜出:

contributeNodesToGraph:将当前对象作为节点(Node)添加到DirectedGraph中。

contributeEdgesToGraph:将当前对象所对应的连线作为边(Edge)添加到DirectedGraph中。

applyGraphResults:将图中生成的布局信息取出,对本对象进行重新布局。

接口中的graph参数就是保存的图的信息,map参数维持一个对象到节点/边的映射,使得每个对象能够方便的找到其对应的图中的节点或者边。这个接口的使用,在后面会有涉及。下面先看看显示图的容器是如何构建的。

 

图的容器定义为GraphDiagramEditPart,这个EditPart对应于要显示的有向图的容器。它实现了GraphBuider接口,这也是我们主要需要关注的接口:

public class GraphDiagramEditPart extends AbstractGraphicalEditPart implements

              GraphBuilder.

 

contributeNodesToGraph方法将自身作为节点添加到图中,但是因为GraphDiagramEditPart对应的是容器,因此它不需要向图中添加信息,只是调用其子EditPart,将其添加到图中。

       public void contributeNodesToGraph(DirectedGraph graph, Map map) {

              for (int i = 0; i < getChildren().size(); i++) {

                     NodeEditPart activity = (NodeEditPart)getChildren().get(i);

                     activity.contributeNodesToGraph(graph, map);

              }

       }

 

contributeEdgesToGraph方法将这个EditPart的所有子EditPart取出,调用其contributeEdgesToGraph方法,通过这个方法,就可以将所有的边添加到图中了:

       public void contributeEdgesToGraph(DirectedGraph graph, Map map) {

              for (int i = 0; i < getChildren().size(); i++) {

                     NodeEditPart child = (NodeEditPart)children.get(i);

                     child.contributeEdgesToGraph(graph, map);

              }

       }

 

applyGraphResults方法将所有取出所有的子EditPart,并调用其applyGraphResults,使得图中所生成的布局信息能够被应用到显示上。

       public void applyGraphResults(DirectedGraph graph, Map map) {

              applyChildrenResults(graph, map);

       }

       protected void applyChildrenResults(DirectedGraph graph, Map map) {

              for (int i = 0; i < getChildren().size(); i++) {

                     GraphBuilder part = (GraphBuilder) getChildren().get(i);

                     part.applyGraphResults(graph, map);

              }

       }

 

下面要介绍的是NodeEditPart,它作图中所有节点所对应的EditPart的抽象父类,也实现了GraphBuilder接口。每一个要做为节点添加到图中的EditPart,应该继承这个类。

public abstract class NodeEditPart extends AbstractGraphicalEditPart implements

              GraphBuilder{

 

       public void contributeNodesToGraph(DirectedGraph graph,

                     Map map) {

              Node n = new Node(this);

              n.outgoingOffset = 7;

              n.incomingOffset = 7;

              n.width = getFigure().getPreferredSize().width;

              n.height = getFigure().getPreferredSize().height;

              n.setPadding(new Insets(10,8,10,12));

              map.put(this, n);

              graph.nodes.add(n);

       }

 

       public void contributeEdgesToGraph(DirectedGraph graph, Map map) {

              List outgoing = getSourceConnections();

              for (int i = 0; i < outgoing.size(); i++) {

                     EdgeEditPart part = (EdgeEditPart)getSourceConnections().get(i);

                     part.contributeEdgesToGraph(graph, map);

              }

       }

 

       public void applyGraphResults(DirectedGraph graph, Map map) {

              Node n = (Node)map.get(this);

              getFigure().setBounds(new Rectangle(n.x, n.y, n.width, n.height));

              for (int i = 0; i < getSourceConnections().size(); i++) {

                     EdgeEditPart trans = (EdgeEditPart) getSourceConnections().get(i);

                     trans.applyGraphResults(graph, map);

              }

       }

}

 

再就是边所对应EditPart的抽象类EdgeEditPart。每一个要作为边添加到图中的EditPart,需要继承这个类。在上面NodeEditPart中对其所对应的Figure其实并没有什么要求,但是对EdgeEditPart所对应的Figure,要求其Figure必须由一个BendpointConnectionRouter,作为其ConnectionRoutersetConnectionRouter(new BendpointConnectionRouter())。这样图的边的路径信息才能够被显示出来。

public abstract class EdgeEditPart extends AbstractConnectionEditPart implements

              GraphBuilder {

 

       public void contributeEdgesToGraph(DirectedGraph graph, Map map) {

              Node source = (Node)map.get(getSource());

              Node target = (Node)map.get(getTarget());

              Edge e = new Edge(this, source, target);

              e.weight = 2;

              graph.edges.add(e);

              map.put(this, e);

       }

 

       public void applyGraphResults(DirectedGraph graph, Map map) {

              Edge e = (Edge)map.get(this);

              NodeList nodes = e.vNodes;

              PolylineConnection conn = (PolylineConnection)getConnectionFigure();

              conn.setTargetDecoration(new PolygonDecoration());

              if (nodes != null) {

                     List bends = new ArrayList();

                     for (int i = 0; i < nodes.size(); i++) {

                            Node vn = nodes.getNode(i);

                            int x = vn.x;

                            int y = vn.y;

                            if (e.isFeedback) {

                                   bends.add(new AbsoluteBendpoint(x, y + vn.height));

                                   bends.add(new AbsoluteBendpoint(x, y));

 

                            } else {

                                   bends.add(new AbsoluteBendpoint(x, y));

                                   bends.add(new AbsoluteBendpoint(x, y + vn.height));

                            }

                     }

                     conn.setRoutingConstraint(bends);

              } else {

                     conn.setRoutingConstraint(Collections.EMPTY_LIST);

              }

       }

}

 

最后的就是一个LayoutManager来初始化图的创建,以及对图的信息进行解释了,生成最终布局了。这个GraphLayoutManager作为GraphDiagramEditPart所对应的GraphDiagramLayoutManager,来显示图的内容。

public class GraphLayoutManager extends AbstractLayout {

       private GraphBuilder diagram;

 

       GraphLayoutManager(GraphBuilder diagram) {

              this.diagram = diagram;

       }

 

       protected Dimension calculatePreferredSize(IFigure container, int wHint,

                     int hHint) {

              container.validate();

              List children = container.getChildren();

              Rectangle result = new Rectangle().setLocation(container

                            .getClientArea().getLocation());

              for (int i = 0; i < children.size(); i++)

                     result.union(((IFigure) children.get(i)).getBounds());

              result.resize(container.getInsets().getWidth(), container.getInsets()

                            .getHeight());

              return result.getSize();

       }

 

       public void layout(IFigure container) {

              DirectedGraph graph = new DirectedGraph();

              Map partsToNodes = new HashMap();

              diagram.contributeNodesToGraph(graph, partsToNodes);

              diagram.contributeEdgesToGraph(graph, partsToNodes);

              new DirectedGraphLayout().visit(graph);

              diagram.applyGraphResults(graph, partsToNodes);

       }

}

可以看到在layout方法中,首先生成了一个DirectedGraph,并调用了contributeNodesToGraph以及contributeEdgesToGraph方法,将节点和边的信息添加到这个生成的DirectedGraphGraph中,然后使用布局算法DirectedGraphLayout().visit(graph)来计算生成图的信息(这里使用了visitor模式)最后调用applyGraphResults将图的信息应用到图形的显示上。

 

至此,所有框架的工作做完了,如果要将模型作为一个有向图显示的话,只需要将模型的容器对象对应于GraphDiagramEditPart(在EditPartFactory中进行映射),为每一个需要表示为节点的对象,对应到一个继承于NodeEditPartEditPart,为每一个需要表示为边的模型对象,对应到一个继承于EdgeEditPartEditPart。这样,就能够将图的布局算法,应用到GEF框架中了。

 

这里写的比较简单,使用起来也会有一些具体的约束。例如在有向图中,是不能够有孤立的节点的。如果使用CompoundDirectedGraph,就不会有这样的问题,CompoundDirectedGraph可以包括子图,可以支持更为复杂的图形。在Flow Example中使用的就是CompoundDirectedGraph。在后面,我或许会将这个框架进行改写,以使其支持CompoundDirectedGraph来进行布局算法。下面的图是一个生成的例子,大家可以看一下效果:

example_1.JPG

这是从OWL文件中读取内容之后生成的一个图的表示。可以看到,OWL的节点通过自动图的自动布局之后,已经有了较好的视觉效果。如果没有这样的布局的话,因为单纯的OWL文件中并不会包含节点的图的信息,图显示出来会变得非常的乱,所有的节点都会堆在一起。





原文地址:http://www.blogjava.net/eclipshine/archive/2005/07/22/8195.aspx

posted @ 2005-12-28 16:53 hopeshared 阅读(652) | 评论 (0)编辑 收藏

第一次听这首歌是坐在班车上的时候,觉得很有意思,很喜欢。奇怪的是居然从sogua和baidu.music上都down不到这首歌,放在这里吧

居然从下载歌曲的站点把上面的控件代码给弄了过来,而且居然能用

歌词如下:

请多指教美女
五十亿人难得遇见了我
你运气还不错
专情我也不是故意想要推荐自己
放眼没人能比
远远就看穿你不温驯
却有一种魅力
我不是痞只是很有本事有个性
能让你动心
oh yeah
my girl 别怀疑
我们的频率现在最靠近
想爱我的数不清我想爱的是你
不是chance chance而已
my girl 看着戏
装深情加体贴多的是苍蝇
我没有那种敌机让你满意
一看见你我就心神不宁喔~
我才不会忘记你
他们缺少温柔不够幽默没有体力
不可能跟我匹敌
你是天生明星只是我
也没那么容易
爱不是游戏
给我机会表现来让你动心
我们的频率现在就拉近
我的头彩就是你爱是高额奖金
my girl 想约你
牵狗狗逛河滨吃碗芒果冰
我只有这点本领逗你开心
有信心就要感动你
直到痛哭流涕
现在就打开最强电力
my girl

posted @ 2005-12-23 11:28 hopeshared 阅读(436) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 21 22 23 24 25 26 27 28 29 下一页 Last