Move message hover effect into converstion view
This commit is contained in:
parent
d55f6691c6
commit
42ae68eb40
|
@ -18,8 +18,14 @@
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkEventBox" id="main_wrap_event_box">
|
||||||
<property name="orientation">vertical</property>
|
<property name="valign">end</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkOverlay">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEventBox" id="main_event_box">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox" id="main">
|
<object class="GtkBox" id="main">
|
||||||
|
@ -31,6 +37,34 @@
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child type="overlay">
|
||||||
|
<object class="GtkBox" id="message_menu_box">
|
||||||
|
<property name="margin-right">10</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">end</property>
|
||||||
|
<property name="valign">start</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuButton" id="emoji_button">
|
||||||
|
<property name="vexpand">False</property>
|
||||||
|
<property name="halign">end</property>
|
||||||
|
<property name="valign">end</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="icon-name">dino-emoticon-add-symbolic</property>
|
||||||
|
<property name="icon-size">1</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="index">-1</property>
|
<property name="index">-1</property>
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class ConversationItemSkeleton : EventBox {
|
||||||
private Box header_content_box = new Box(Orientation.VERTICAL, 0) { visible=true };
|
private Box header_content_box = new Box(Orientation.VERTICAL, 0) { visible=true };
|
||||||
private ItemMetaDataHeader metadata_header;
|
private ItemMetaDataHeader metadata_header;
|
||||||
|
|
||||||
public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item) {
|
public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item, bool initial_item) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
|
@ -44,23 +44,17 @@ public class ConversationItemSkeleton : EventBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
image_content_box.add(header_content_box);
|
image_content_box.add(header_content_box);
|
||||||
this.add(image_content_box);
|
|
||||||
|
|
||||||
if (item.get_type().is_a(typeof(ContentMetaItem))) {
|
if (initial_item) {
|
||||||
this.motion_notify_event.connect((event) => {
|
this.add(image_content_box);
|
||||||
this.set_state_flags(StateFlags.PRELIGHT, false);
|
} else {
|
||||||
return false;
|
Revealer revealer = new Revealer() { transition_duration=200, transition_type = RevealerTransitionType.SLIDE_UP, visible = true };
|
||||||
});
|
revealer.add_with_properties(image_content_box);
|
||||||
this.enter_notify_event.connect((event) => {
|
revealer.reveal_child = true;
|
||||||
this.set_state_flags(StateFlags.PRELIGHT, false);
|
this.add(revealer);
|
||||||
return false;
|
|
||||||
});
|
|
||||||
this.leave_notify_event.connect((event) => {
|
|
||||||
this.unset_state_flags(StateFlags.PRELIGHT);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.notify["show-skeleton"].connect(update_margin);
|
this.notify["show-skeleton"].connect(update_margin);
|
||||||
this.notify["last-group-item"].connect(update_margin);
|
this.notify["last-group-item"].connect(update_margin);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Gee;
|
using Gee;
|
||||||
using Gtk;
|
using Gtk;
|
||||||
|
using Gdk;
|
||||||
using Pango;
|
using Pango;
|
||||||
|
|
||||||
using Dino.Entities;
|
using Dino.Entities;
|
||||||
|
@ -13,8 +14,11 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
|
|
||||||
[GtkChild] public ScrolledWindow scrolled;
|
[GtkChild] public ScrolledWindow scrolled;
|
||||||
[GtkChild] private Revealer notification_revealer;
|
[GtkChild] private Revealer notification_revealer;
|
||||||
|
[GtkChild] private Box message_menu_box;
|
||||||
[GtkChild] private Box notifications;
|
[GtkChild] private Box notifications;
|
||||||
[GtkChild] private Box main;
|
[GtkChild] private Box main;
|
||||||
|
[GtkChild] private EventBox main_event_box;
|
||||||
|
[GtkChild] private EventBox main_wrap_event_box;
|
||||||
[GtkChild] private Stack stack;
|
[GtkChild] private Stack stack;
|
||||||
|
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
|
@ -25,6 +29,7 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
private Gee.List<ConversationItemSkeleton> item_skeletons = new Gee.ArrayList<ConversationItemSkeleton>();
|
private Gee.List<ConversationItemSkeleton> item_skeletons = new Gee.ArrayList<ConversationItemSkeleton>();
|
||||||
private ContentProvider content_populator;
|
private ContentProvider content_populator;
|
||||||
private SubscriptionNotitication subscription_notification;
|
private SubscriptionNotitication subscription_notification;
|
||||||
|
private bool enable_menu_box = false;
|
||||||
|
|
||||||
private double? was_value;
|
private double? was_value;
|
||||||
private double? was_upper;
|
private double? was_upper;
|
||||||
|
@ -35,6 +40,10 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
private bool firstLoad = true;
|
private bool firstLoad = true;
|
||||||
private bool at_current_content = true;
|
private bool at_current_content = true;
|
||||||
private bool reload_messages = true;
|
private bool reload_messages = true;
|
||||||
|
Widget currently_highlighted = null;
|
||||||
|
ContentItem current_highlighted_item = null;
|
||||||
|
bool mouse_inside = false;
|
||||||
|
int last_y_root = -1;
|
||||||
|
|
||||||
public ConversationView init(StreamInteractor stream_interactor) {
|
public ConversationView init(StreamInteractor stream_interactor) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
|
@ -57,9 +66,89 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
main_wrap_event_box.events = EventMask.ENTER_NOTIFY_MASK;
|
||||||
|
main_wrap_event_box.events = EventMask.LEAVE_NOTIFY_MASK;
|
||||||
|
main_wrap_event_box.leave_notify_event.connect(on_leave_notify_event);
|
||||||
|
main_wrap_event_box.enter_notify_event.connect(on_enter_notify_event);
|
||||||
|
main_event_box.events = EventMask.POINTER_MOTION_MASK;
|
||||||
|
main_event_box.motion_notify_event.connect(on_motion_notify_event);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool on_enter_notify_event(Gdk.EventCrossing event) {
|
||||||
|
mouse_inside = true;
|
||||||
|
update_highlight((int)event.x_root, (int)event.y_root);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool on_leave_notify_event(Gdk.EventCrossing event) {
|
||||||
|
mouse_inside = false;
|
||||||
|
if (currently_highlighted != null) currently_highlighted.unset_state_flags(StateFlags.PRELIGHT);
|
||||||
|
message_menu_box.visible = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool on_motion_notify_event(Gdk.EventMotion event) {
|
||||||
|
mouse_inside = true;
|
||||||
|
update_highlight((int)event.x_root, (int)event.y_root);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update_highlight(int x_root, int y_root) {
|
||||||
|
if ((last_y_root - y_root).abs() <= 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_y_root = y_root;
|
||||||
|
message_menu_box.visible = enable_menu_box;
|
||||||
|
|
||||||
|
// Get pointer location in main
|
||||||
|
int geometry_x, geometry_y, geometry_width, geometry_height, dest_x, dest_y;
|
||||||
|
Widget toplevel_widget = this.get_toplevel();
|
||||||
|
toplevel_widget.get_window().get_geometry(out geometry_x, out geometry_y, out geometry_width, out geometry_height);
|
||||||
|
toplevel_widget.translate_coordinates(main, x_root - geometry_x, y_root - geometry_y, out dest_x, out dest_y);
|
||||||
|
|
||||||
|
// Get widget under pointer
|
||||||
|
int h = 0;
|
||||||
|
bool @break = false;
|
||||||
|
Widget w = null;
|
||||||
|
main.@foreach((widget) => {
|
||||||
|
if (break) return;
|
||||||
|
|
||||||
|
h += widget.get_allocated_height();
|
||||||
|
w = widget;
|
||||||
|
if (h >= dest_y) {
|
||||||
|
@break = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get widget coordinates in main
|
||||||
|
int widget_x, widget_y;
|
||||||
|
w.translate_coordinates(main, 0, 0, out widget_x, out widget_y);
|
||||||
|
|
||||||
|
// Get MessageItem
|
||||||
|
var iter = widgets.map_iterator();
|
||||||
|
while (iter.next()) {
|
||||||
|
if (iter.get_value() == w) {
|
||||||
|
Plugins.MetaConversationItem meta_item = iter.get_key();
|
||||||
|
var meta_content_item = meta_item as ContentMetaItem;
|
||||||
|
if (meta_content_item == null) return;
|
||||||
|
current_highlighted_item = meta_content_item.content_item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight widget
|
||||||
|
if (currently_highlighted != null) currently_highlighted.unset_state_flags(StateFlags.PRELIGHT);
|
||||||
|
w.set_state_flags(StateFlags.PRELIGHT, true);
|
||||||
|
currently_highlighted = w;
|
||||||
|
|
||||||
|
// Move message menu
|
||||||
|
message_menu_box.margin_top = widget_y - 10;
|
||||||
|
}
|
||||||
|
|
||||||
public void initialize_for_conversation(Conversation? conversation) {
|
public void initialize_for_conversation(Conversation? conversation) {
|
||||||
// Workaround for rendering issues
|
// Workaround for rendering issues
|
||||||
if (firstLoad) {
|
if (firstLoad) {
|
||||||
|
@ -75,6 +164,8 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
initialize_for_conversation_(conversation);
|
initialize_for_conversation_(conversation);
|
||||||
display_latest();
|
display_latest();
|
||||||
stack.set_visible_child_name("main");
|
stack.set_visible_child_name("main");
|
||||||
|
|
||||||
|
enable_menu_box = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize_around_message(Conversation conversation, ContentItem content_item) {
|
public void initialize_around_message(Conversation conversation, ContentItem content_item) {
|
||||||
|
@ -231,24 +322,15 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
Plugins.MetaConversationItem? lower_item = meta_items.lower(item);
|
Plugins.MetaConversationItem? lower_item = meta_items.lower(item);
|
||||||
|
|
||||||
// Fill datastructure
|
// Fill datastructure
|
||||||
ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation, item) { visible=true };
|
ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation, item, !animate) { visible=true };
|
||||||
item_item_skeletons[item] = item_skeleton;
|
item_item_skeletons[item] = item_skeleton;
|
||||||
int index = lower_item != null ? item_skeletons.index_of(item_item_skeletons[lower_item]) + 1 : 0;
|
int index = lower_item != null ? item_skeletons.index_of(item_item_skeletons[lower_item]) + 1 : 0;
|
||||||
item_skeletons.insert(index, item_skeleton);
|
item_skeletons.insert(index, item_skeleton);
|
||||||
|
|
||||||
// Insert widget
|
// Insert widget
|
||||||
Widget insert = item_skeleton;
|
widgets[item] = item_skeleton;
|
||||||
if (animate) {
|
main.add(item_skeleton);
|
||||||
Revealer revealer = new Revealer() {transition_duration = 200, transition_type = RevealerTransitionType.SLIDE_UP, visible = true};
|
main.reorder_child(item_skeleton, index);
|
||||||
revealer.add(item_skeleton);
|
|
||||||
insert = revealer;
|
|
||||||
main.add(insert);
|
|
||||||
revealer.reveal_child = true;
|
|
||||||
} else {
|
|
||||||
main.add(insert);
|
|
||||||
}
|
|
||||||
widgets[item] = insert;
|
|
||||||
main.reorder_child(insert, index);
|
|
||||||
|
|
||||||
if (lower_item != null) {
|
if (lower_item != null) {
|
||||||
if (can_merge(item, lower_item)) {
|
if (can_merge(item, lower_item)) {
|
||||||
|
@ -279,7 +361,7 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insert;
|
return item_skeleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool can_merge(Plugins.MetaConversationItem upper_item /*more recent, displayed below*/, Plugins.MetaConversationItem lower_item /*less recent, displayed above*/) {
|
private bool can_merge(Plugins.MetaConversationItem upper_item /*more recent, displayed below*/, Plugins.MetaConversationItem lower_item /*less recent, displayed above*/) {
|
||||||
|
|
Loading…
Reference in a new issue