mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-18 04:36:30 +01:00
(1) remove almost-never used block/unlock_property_changes() methods from PBD::Stateful (2) hide used and path columns from region list (3) detect mouse position within MIDI notes and thus allow move or trim from the same mouse mode (object or trim; first & last 1/4 of each note is for trimming
git-svn-id: svn://localhost/ardour2/branches/3.0@7823 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
e6ecd36b26
commit
90e73a3a6d
14 changed files with 131 additions and 33 deletions
|
|
@ -488,7 +488,7 @@ AudioStreamView::setup_rec_box ()
|
||||||
boost::dynamic_pointer_cast<AudioRegion>(RegionFactory::create (sources, plist, false)));
|
boost::dynamic_pointer_cast<AudioRegion>(RegionFactory::create (sources, plist, false)));
|
||||||
|
|
||||||
assert(region);
|
assert(region);
|
||||||
region->block_property_changes ();
|
region->suspend_property_changes ();
|
||||||
region->set_position (_trackview.session()->transport_frame(), this);
|
region->set_position (_trackview.session()->transport_frame(), this);
|
||||||
rec_regions.push_back (make_pair(region, (RegionView*) 0));
|
rec_regions.push_back (make_pair(region, (RegionView*) 0));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item, const boost
|
||||||
, _note(note)
|
, _note(note)
|
||||||
, _selected(false)
|
, _selected(false)
|
||||||
, _valid (true)
|
, _valid (true)
|
||||||
|
, _mouse_x_fraction (-1.0)
|
||||||
|
, _mouse_y_fraction (-1.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,6 +225,60 @@ CanvasNoteEvent::base_color()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CanvasNoteEvent::set_mouse_fractions (GdkEvent* ev)
|
||||||
|
{
|
||||||
|
double ix, iy;
|
||||||
|
double bx1, bx2, by1, by2;
|
||||||
|
|
||||||
|
switch (ev->type) {
|
||||||
|
case GDK_MOTION_NOTIFY:
|
||||||
|
ix = ev->motion.x;
|
||||||
|
iy = ev->motion.y;
|
||||||
|
break;
|
||||||
|
case GDK_ENTER_NOTIFY:
|
||||||
|
ix = ev->crossing.x;
|
||||||
|
iy = ev->crossing.y;
|
||||||
|
break;
|
||||||
|
case GDK_BUTTON_PRESS:
|
||||||
|
case GDK_BUTTON_RELEASE:
|
||||||
|
ix = ev->button.x;
|
||||||
|
iy = ev->button.y;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_mouse_x_fraction = -1.0;
|
||||||
|
_mouse_y_fraction = -1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_item->get_bounds (bx1, by1, bx2, by2);
|
||||||
|
_item->w2i (ix, iy);
|
||||||
|
/* hmm, something wrong here. w2i should give item-local coordinates
|
||||||
|
but it doesn't. for now, finesse this.
|
||||||
|
*/
|
||||||
|
ix = ix - bx1;
|
||||||
|
iy = iy - by1;
|
||||||
|
|
||||||
|
/* fraction of width/height */
|
||||||
|
double xf;
|
||||||
|
double yf;
|
||||||
|
bool notify = false;
|
||||||
|
|
||||||
|
xf = ix / (bx2 - bx1);
|
||||||
|
yf = iy / (by2 - by1);
|
||||||
|
|
||||||
|
if (xf != _mouse_x_fraction || yf != _mouse_y_fraction) {
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mouse_x_fraction = xf;
|
||||||
|
_mouse_y_fraction = yf;
|
||||||
|
|
||||||
|
if (notify) {
|
||||||
|
_region.note_mouse_position (_mouse_x_fraction, _mouse_y_fraction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CanvasNoteEvent::on_event(GdkEvent* ev)
|
CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
{
|
{
|
||||||
|
|
@ -232,22 +288,21 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
|
|
||||||
switch (ev->type) {
|
switch (ev->type) {
|
||||||
case GDK_ENTER_NOTIFY:
|
case GDK_ENTER_NOTIFY:
|
||||||
|
set_mouse_fractions (ev);
|
||||||
_region.note_entered (this);
|
_region.note_entered (this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_LEAVE_NOTIFY:
|
case GDK_LEAVE_NOTIFY:
|
||||||
|
set_mouse_fractions (ev);
|
||||||
_region.note_left (this);
|
_region.note_left (this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
double ix, iy;
|
set_mouse_fractions (ev);
|
||||||
ix = ev->motion.x;
|
|
||||||
iy = ev->motion.y;
|
|
||||||
_item->w2i (ix, iy);
|
|
||||||
cerr << "note motion at " << ix << ',' << iy << endl;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
|
set_mouse_fractions (ev);
|
||||||
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
|
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
|
||||||
show_channel_selector();
|
show_channel_selector();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -255,6 +310,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
set_mouse_fractions (ev);
|
||||||
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
|
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -267,6 +323,13 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CanvasNoteEvent::mouse_near_ends () const
|
||||||
|
{
|
||||||
|
return (_mouse_x_fraction >= 0.0 && _mouse_x_fraction < 0.25) ||
|
||||||
|
(_mouse_x_fraction >= 0.75 && _mouse_x_fraction < 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Canvas
|
} // namespace Canvas
|
||||||
} // namespace Gnome
|
} // namespace Gnome
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,8 @@ class CanvasNoteEvent : virtual public sigc::trackable
|
||||||
/// hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
|
/// hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
|
||||||
static const uint32_t midi_channel_colors[16];
|
static const uint32_t midi_channel_colors[16];
|
||||||
|
|
||||||
|
bool mouse_near_ends () const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum State { None, Pressed, Dragging };
|
enum State { None, Pressed, Dragging };
|
||||||
|
|
||||||
|
|
@ -151,6 +153,10 @@ protected:
|
||||||
bool _own_note;
|
bool _own_note;
|
||||||
bool _selected;
|
bool _selected;
|
||||||
bool _valid;
|
bool _valid;
|
||||||
|
float _mouse_x_fraction;
|
||||||
|
float _mouse_y_fraction;
|
||||||
|
|
||||||
|
void set_mouse_fractions (GdkEvent*);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Gnome
|
} // namespace Gnome
|
||||||
|
|
|
||||||
|
|
@ -476,6 +476,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||||
static Gdk::Cursor* timebar_cursor;
|
static Gdk::Cursor* timebar_cursor;
|
||||||
static Gdk::Cursor* transparent_cursor;
|
static Gdk::Cursor* transparent_cursor;
|
||||||
|
|
||||||
|
Gdk::Cursor* get_canvas_cursor () const { return current_canvas_cursor; }
|
||||||
|
void set_canvas_cursor (Gdk::Cursor*);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void map_transport_state ();
|
void map_transport_state ();
|
||||||
void map_position_change (framepos_t);
|
void map_position_change (framepos_t);
|
||||||
|
|
@ -686,8 +689,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||||
Gtk::VBox vpacker;
|
Gtk::VBox vpacker;
|
||||||
|
|
||||||
Gdk::Cursor* current_canvas_cursor;
|
Gdk::Cursor* current_canvas_cursor;
|
||||||
void set_canvas_cursor ();
|
|
||||||
Gdk::Cursor* which_grabber_cursor ();
|
Gdk::Cursor* which_grabber_cursor ();
|
||||||
|
void set_canvas_cursor ();
|
||||||
|
|
||||||
ArdourCanvas::Canvas* track_canvas;
|
ArdourCanvas::Canvas* track_canvas;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -917,6 +917,14 @@ Editor::horizontal_position () const
|
||||||
{
|
{
|
||||||
return frame_to_unit (leftmost_frame);
|
return frame_to_unit (leftmost_frame);
|
||||||
}
|
}
|
||||||
|
void
|
||||||
|
Editor::set_canvas_cursor (Gdk::Cursor* cursor)
|
||||||
|
{
|
||||||
|
if (is_drawable()) {
|
||||||
|
track_canvas->get_window()->set_cursor(*cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Editor::track_canvas_key_press (GdkEventKey* event)
|
Editor::track_canvas_key_press (GdkEventKey* event)
|
||||||
|
|
|
||||||
|
|
@ -3769,7 +3769,7 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_region->note_dropped (_primary, total_dx(), - total_dy());
|
_region->note_dropped (_primary, total_dx(), total_dy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
|
#include "canvas-note.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "time_axis_view.h"
|
#include "time_axis_view.h"
|
||||||
#include "audio_time_axis.h"
|
#include "audio_time_axis.h"
|
||||||
|
|
@ -677,14 +678,16 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||||
case NoteItem:
|
case NoteItem:
|
||||||
if (internal_editing()) {
|
if (internal_editing()) {
|
||||||
/* trim notes if we're in internal edit mode and near the ends of the note */
|
/* trim notes if we're in internal edit mode and near the ends of the note */
|
||||||
|
ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
|
||||||
|
if (cn->mouse_near_ends()) {
|
||||||
_drags->set (new NoteResizeDrag (this, item), event);
|
_drags->set (new NoteResizeDrag (this, item), event);
|
||||||
|
} else {
|
||||||
|
_drags->set (new NoteDrag (this, item), event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case StreamItem:
|
case StreamItem:
|
||||||
cerr << "press on stream item, internal? " << internal_editing() << " MIDI ? "
|
|
||||||
<< dynamic_cast<MidiTimeAxisView*>(clicked_axisview)
|
|
||||||
<< endl;
|
|
||||||
if (internal_editing()) {
|
if (internal_editing()) {
|
||||||
if (dynamic_cast<MidiTimeAxisView*> (clicked_axisview)) {
|
if (dynamic_cast<MidiTimeAxisView*> (clicked_axisview)) {
|
||||||
_drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
|
_drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
|
||||||
|
|
@ -718,7 +721,12 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
||||||
switch (item_type) {
|
switch (item_type) {
|
||||||
case NoteItem:
|
case NoteItem:
|
||||||
if (internal_editing()) {
|
if (internal_editing()) {
|
||||||
|
ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
|
||||||
|
if (cn->mouse_near_ends()) {
|
||||||
|
_drags->set (new NoteResizeDrag (this, item), event);
|
||||||
|
} else {
|
||||||
_drags->set (new NoteDrag (this, item), event);
|
_drags->set (new NoteDrag (this, item), event);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ EditorRegions::EditorRegions (Editor* e)
|
||||||
_display.append_column (_("G"), _columns.glued);
|
_display.append_column (_("G"), _columns.glued);
|
||||||
_display.append_column (_("M"), _columns.muted);
|
_display.append_column (_("M"), _columns.muted);
|
||||||
_display.append_column (_("O"), _columns.opaque);
|
_display.append_column (_("O"), _columns.opaque);
|
||||||
_display.append_column (_("Used"), _columns.used);
|
// _display.append_column (_("Used"), _columns.used);
|
||||||
_display.append_column (_("Path"), _columns.path);
|
// _display.append_column (_("Path"), _columns.path);
|
||||||
_display.set_headers_visible (true);
|
_display.set_headers_visible (true);
|
||||||
//_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH);
|
//_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH);
|
||||||
|
|
||||||
|
|
@ -461,10 +461,6 @@ EditorRegions::selection_changed ()
|
||||||
// they could have clicked on a row that is just a placeholder, like "Hidden"
|
// they could have clicked on a row that is just a placeholder, like "Hidden"
|
||||||
if (region) {
|
if (region) {
|
||||||
|
|
||||||
cerr << "Selected region has use count "
|
|
||||||
<< _session->playlists->region_use_count (region)
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
if (region->automatic()) {
|
if (region->automatic()) {
|
||||||
|
|
||||||
_display.get_selection()->unselect(*i);
|
_display.get_selection()->unselect(*i);
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include "canvas-hit.h"
|
#include "canvas-hit.h"
|
||||||
#include "canvas-note.h"
|
#include "canvas-note.h"
|
||||||
#include "canvas-program-change.h"
|
#include "canvas-program-change.h"
|
||||||
|
#include "editor.h"
|
||||||
#include "ghostregion.h"
|
#include "ghostregion.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
|
@ -2646,6 +2647,10 @@ MidiRegionView::change_channel(uint8_t channel)
|
||||||
void
|
void
|
||||||
MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev)
|
MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev)
|
||||||
{
|
{
|
||||||
|
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
|
||||||
|
|
||||||
|
pre_enter_cursor = editor->get_canvas_cursor ();
|
||||||
|
|
||||||
if (_mouse_state == SelectTouchDragging) {
|
if (_mouse_state == SelectTouchDragging) {
|
||||||
note_selected (ev, true);
|
note_selected (ev, true);
|
||||||
}
|
}
|
||||||
|
|
@ -2656,17 +2661,28 @@ MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev)
|
||||||
void
|
void
|
||||||
MidiRegionView::note_left (ArdourCanvas::CanvasNoteEvent* note)
|
MidiRegionView::note_left (ArdourCanvas::CanvasNoteEvent* note)
|
||||||
{
|
{
|
||||||
|
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
|
||||||
|
|
||||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||||
(*i)->hide_velocity ();
|
(*i)->hide_velocity ();
|
||||||
}
|
}
|
||||||
|
|
||||||
trackview.editor().hide_verbose_canvas_cursor ();
|
editor->hide_verbose_canvas_cursor ();
|
||||||
|
editor->set_canvas_cursor (pre_enter_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::note_motion (float fraction)
|
MidiRegionView::note_mouse_position (float x_fraction, float y_fraction)
|
||||||
{
|
{
|
||||||
cerr << "Now at " << fraction << " within note\n";
|
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
|
||||||
|
|
||||||
|
if (x_fraction > 0.0 && x_fraction < 0.25) {
|
||||||
|
editor->set_canvas_cursor (editor->left_side_trim_cursor);
|
||||||
|
} else if (x_fraction >= 0.75 && x_fraction < 1.0) {
|
||||||
|
editor->set_canvas_cursor (editor->right_side_trim_cursor);
|
||||||
|
} else {
|
||||||
|
editor->set_canvas_cursor (pre_enter_cursor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -190,9 +190,11 @@ class MidiRegionView : public RegionView
|
||||||
void apply_diff_as_subcommand();
|
void apply_diff_as_subcommand();
|
||||||
void abort_command();
|
void abort_command();
|
||||||
|
|
||||||
|
Gdk::Cursor* pre_enter_cursor;
|
||||||
|
|
||||||
void note_entered(ArdourCanvas::CanvasNoteEvent* ev);
|
void note_entered(ArdourCanvas::CanvasNoteEvent* ev);
|
||||||
void note_left(ArdourCanvas::CanvasNoteEvent* ev);
|
void note_left(ArdourCanvas::CanvasNoteEvent* ev);
|
||||||
void note_motion (float fraction);
|
void note_mouse_position (float xfraction, float yfraction);
|
||||||
void unique_select(ArdourCanvas::CanvasNoteEvent* ev);
|
void unique_select(ArdourCanvas::CanvasNoteEvent* ev);
|
||||||
void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend=false);
|
void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend=false);
|
||||||
void note_deselected(ArdourCanvas::CanvasNoteEvent* ev);
|
void note_deselected(ArdourCanvas::CanvasNoteEvent* ev);
|
||||||
|
|
@ -432,7 +434,6 @@ class MidiRegionView : public RegionView
|
||||||
void get_events (Events& e, Evoral::Sequence<Evoral::MusicalTime>::NoteOperator op, uint8_t val, int chan_mask = 0);
|
void get_events (Events& e, Evoral::Sequence<Evoral::MusicalTime>::NoteOperator op, uint8_t val, int chan_mask = 0);
|
||||||
|
|
||||||
void display_program_changes_on_channel (uint8_t);
|
void display_program_changes_on_channel (uint8_t);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -459,7 +459,7 @@ MidiStreamView::setup_rec_box ()
|
||||||
(RegionFactory::create (sources, plist, false)));
|
(RegionFactory::create (sources, plist, false)));
|
||||||
|
|
||||||
assert(region);
|
assert(region);
|
||||||
region->block_property_changes ();
|
region->suspend_property_changes ();
|
||||||
region->set_position (_trackview.session()->transport_frame(), this);
|
region->set_position (_trackview.session()->transport_frame(), this);
|
||||||
rec_regions.push_back (make_pair(region, (RegionView*)0));
|
rec_regions.push_back (make_pair(region, (RegionView*)0));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1310,7 +1310,7 @@ Region::send_change (const PropertyChange& what_changed)
|
||||||
|
|
||||||
Stateful::send_change (what_changed);
|
Stateful::send_change (what_changed);
|
||||||
|
|
||||||
if (!_no_property_changes) {
|
if (!Stateful::frozen()) {
|
||||||
|
|
||||||
/* Try and send a shared_pointer unless this is part of the constructor.
|
/* Try and send a shared_pointer unless this is part of the constructor.
|
||||||
If so, do nothing.
|
If so, do nothing.
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,7 @@ class Stateful {
|
||||||
virtual void suspend_property_changes ();
|
virtual void suspend_property_changes ();
|
||||||
virtual void resume_property_changes ();
|
virtual void resume_property_changes ();
|
||||||
|
|
||||||
void unlock_property_changes () { _no_property_changes = false; }
|
virtual bool frozen() const { return _frozen; }
|
||||||
void block_property_changes () { _no_property_changes = true; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
@ -108,7 +107,6 @@ class Stateful {
|
||||||
XMLNode *_instant_xml;
|
XMLNode *_instant_xml;
|
||||||
PBD::ID _id;
|
PBD::ID _id;
|
||||||
int32_t _frozen;
|
int32_t _frozen;
|
||||||
bool _no_property_changes;
|
|
||||||
PBD::PropertyChange _pending_changed;
|
PBD::PropertyChange _pending_changed;
|
||||||
Glib::Mutex _lock;
|
Glib::Mutex _lock;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ int Stateful::loading_state_version = 0;
|
||||||
|
|
||||||
Stateful::Stateful ()
|
Stateful::Stateful ()
|
||||||
: _frozen (0)
|
: _frozen (0)
|
||||||
, _no_property_changes (false)
|
|
||||||
, _properties (new OwnedPropertyList)
|
, _properties (new OwnedPropertyList)
|
||||||
{
|
{
|
||||||
_extra_xml = 0;
|
_extra_xml = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue