public void ConversionToStringTest()
        {
            var stringTypeInfo = new StorageTypeInfo(typeof(string), null, 100);
            var typeList       = new[] {
                typeof(string),
                typeof(short),
                typeof(int),
                typeof(long),
                typeof(ushort),
                typeof(uint),
                typeof(ulong),
                typeof(char),
                typeof(byte),
                typeof(sbyte)
            };

            foreach (var type in typeList)
            {
                Assert.IsTrue(TypeConversionVerifier
                              .CanConvert(new StorageTypeInfo(type, null), stringTypeInfo));
            }
            typeList = new[] {
                typeof(Guid),
                typeof(DateTime),
                typeof(TimeSpan),
                typeof(byte[])
            };
            foreach (var type in typeList)
            {
                Assert.IsFalse(TypeConversionVerifier
                               .CanConvert(new StorageTypeInfo(type, null), stringTypeInfo));
            }
        }
        /// <summary>
        /// Verifies whether the source type can be converted to the target
        /// type without loss of data.
        /// </summary>
        /// <param name="from">The source type.</param>
        /// <param name="to">The target type.</param>
        /// <returns>
        /// <see langword="true"/> if the source type can be converted to the
        /// target type without loss of data; otherwise, <see langword="false"/>.
        /// </returns>
        public static bool CanConvertSafely(StorageTypeInfo from, StorageTypeInfo to)
        {
            ArgumentValidator.EnsureArgumentNotNull(from, "from");
            ArgumentValidator.EnsureArgumentNotNull(to, "to");

            // Truncation and precision loss is NOT ALLOWED by this method

            if (!CanConvert(from, to))
            {
                return(false);
            }
            if (from.IsNullable && !to.IsNullable)
            {
                return(false); // Can't convert NULL
            }
            var toType   = to.Type.StripNullable();
            var fromType = from.Type.StripNullable();

            if (toType == WellKnownTypes.Decimal && fromType == WellKnownTypes.Decimal)
            {
                return(CheckScaleAndPrecision(from, to));
            }
            else if (toType == WellKnownTypes.String && fromType == WellKnownTypes.String)
            {
                return(CheckLength(from, to));
            }
            else if (toType == WellKnownTypes.ByteArray && fromType == WellKnownTypes.ByteArray)
            {
                return(CheckLength(from, to));
            }
            return(true);
        }
        /// <summary>
        /// Verifies whether the source type can be converted to the target type.
        /// Loss of data is allowed.
        /// </summary>
        /// <param name="from">The source type.</param>
        /// <param name="to">The target type.</param>
        /// <returns>
        /// <see langword="true"/> if the source type can be converted to the
        /// target type; otherwise, <see langword="false"/>.
        /// </returns>
        public static bool CanConvert(StorageTypeInfo from, StorageTypeInfo to)
        {
            ArgumentValidator.EnsureArgumentNotNull(from, "from");
            ArgumentValidator.EnsureArgumentNotNull(to, "to");

            // Truncation and precision loss is ALLOWED by this method

            if (from.IsTypeUndefined || to.IsTypeUndefined)
            {
                return(false);
            }

            var fromType = from.Type.StripNullable();
            var toType   = to.Type.StripNullable();

            if (fromType == toType) // Comparing just types
            {
                return(true);
            }

            // Types are different
            if (toType == WellKnownTypes.String)
            {
                // Checking target string length
                return(!to.Length.HasValue || CanConvertToString(from, to.Length.Value));
            }

            return(supportedConversions.ContainsKey(fromType) && supportedConversions[fromType].Contains(toType));
        }
        public void ConversionToStringTest()
        {
            var stringTypeInfo = new StorageTypeInfo(typeof(String), null, 100);
            var typeList       = new[] {
                typeof(String),
                typeof(Int16),
                typeof(Int32),
                typeof(Int64),
                typeof(UInt16),
                typeof(UInt32),
                typeof(UInt64),
                typeof(Char),
                typeof(Byte),
                typeof(SByte)
            };

            foreach (var type in typeList)
            {
                Assert.IsTrue(TypeConversionVerifier
                              .CanConvert(new StorageTypeInfo(type, null), stringTypeInfo));
            }
            typeList = new[] {
                typeof(Guid),
                typeof(DateTime),
                typeof(TimeSpan),
                typeof(Byte[])
            };
            foreach (var type in typeList)
            {
                Assert.IsFalse(TypeConversionVerifier
                               .CanConvert(new StorageTypeInfo(type, null), stringTypeInfo));
            }
        }
 private static bool IsOnlyNullableChanged(StorageTypeInfo source, StorageTypeInfo target)
 {
     return(source.Scale == target.Scale &&
            source.Precision == target.Precision &&
            source.NativeType == target.NativeType &&
            source.Length == target.Length &&
            source.IsNullable != target.IsNullable);
 }
        private static bool IsOnlyNullableChanged(StorageTypeInfo source, StorageTypeInfo target)
        {
            var a = source.Scale == target.Scale;
            var b = source.Precision == target.Precision;
            var c = source.NativeType == target.NativeType;
            var d = source.Length == target.Length;
            var e = source.IsNullable != target.IsNullable;

            return(a && b && c && d && e);
        }
        public void CanConvertSafelyTest()
        {
            var sourceType = new StorageTypeInfo(typeof(string), null, 10);
            var targetType = new StorageTypeInfo(typeof(string), null, 5);

            Assert.IsTrue(TypeConversionVerifier.CanConvert(sourceType, targetType));
            Assert.IsFalse(TypeConversionVerifier.CanConvertSafely(sourceType, targetType));
            targetType = new StorageTypeInfo(typeof(string), null, 10);
            Assert.IsTrue(TypeConversionVerifier.CanConvertSafely(sourceType, targetType));
            targetType = new StorageTypeInfo(typeof(string), null, 11);
            Assert.IsTrue(TypeConversionVerifier.CanConvertSafely(sourceType, targetType));
        }
 private static bool CheckLength(StorageTypeInfo from, StorageTypeInfo to)
 {
     if (!to.Length.HasValue)
     {
         return(true); // Conversion to Var*(max) is always possible, or both types have no length
     }
     if (!from.Length.HasValue)
     {
         return(false); // Conversion from Var*(max) is possible only to Var*(max)
     }
     // Otherwise it's possible to convert only when new type has higher length
     return(from.Length.Value <= to.Length.Value);
 }
        private StorageTypeInfo GetStorageTypeInfo(StorageTypeInfo typeInfo, StorageColumnInfo extractedConnectedColumn, ColumnInfo column)
        {
            if (!isUpgradingStage)
            {
                return(typeInfo);
            }
            if (extractedConnectedColumn == null)
            {
                return(typeInfo);
            }
            var extractedTypeInfo = extractedConnectedColumn.Type;

            if (IsOnlyNullableChanged(typeInfo, extractedTypeInfo))
            {
                var underlyingType = Nullable.GetUnderlyingType(typeInfo.Type);
                var type           = underlyingType ?? typeInfo.Type;
                var isNullable     = column.Field.Attributes.HasFlag(FieldAttributes.DeclaredAsNullable);
                return(new StorageTypeInfo(ToNullable(type, isNullable), typeInfo.NativeType, isNullable, typeInfo.Length, typeInfo.Precision, typeInfo.Scale));
            }
            return(typeInfo);
        }
        private static bool CanConvertToString(StorageTypeInfo from, int length)
        {
            switch (Type.GetTypeCode(from.Type.StripNullable()))
            {
            case TypeCode.Char:
            case TypeCode.String:
                return(true);

            case TypeCode.Decimal:
                return(length >= from.Precision + 2);

            case TypeCode.Byte:
                return(length >= 3);

            case TypeCode.SByte:
                return(length >= 4);

            case TypeCode.Int16:
                return(length >= 6);

            case TypeCode.Int32:
                return(length >= 11);

            case TypeCode.Int64:
                return(length >= 20);

            case TypeCode.UInt16:
                return(length >= 5);

            case TypeCode.UInt32:
                return(length >= 10);

            case TypeCode.UInt64:
                return(length >= 20);

            default:
                return(false);
            }
        }
        private object GetColumnDefaultValue(ColumnInfo column, StorageTypeInfo typeInfo)
        {
            if (column.DefaultValue != null)
            {
                return(column.DefaultValue);
            }

            if (column.IsNullable)
            {
                return(null);
            }

            var type = typeInfo.Type;

            if (type == typeof(string))
            {
                return(string.Empty);
            }
            if (type == typeof(byte[]))
            {
                return(ArrayUtils <byte> .EmptyArray);
            }
            return(Activator.CreateInstance(column.ValueType));
        }
        /// <inheritdoc/>
        protected override IPathNode VisitColumnInfo(ColumnInfo column)
        {
            var nonNullableType = column.ValueType;
            var nullableType    = ToNullable(nonNullableType, column.IsNullable);

            StorageColumnInfo extractedConnectedColumn = null;

            if (isUpgradingStage && ShouldGetExtractedColumnInformation(column))
            {
                extractedConnectedColumn = GetExtractedStorageColumnInfoFor(column);
            }

            var typeInfoPrototype = new StorageTypeInfo(nullableType, null, column.IsNullable, column.Length, column.Precision, column.Scale);
            var nativeTypeInfo    = CreateType(nonNullableType, column.Length, column.Precision, column.Scale);

            // We need the same type as in SQL database here (i.e. the same as native)
            var typeInfo      = new StorageTypeInfo(ToNullable(nativeTypeInfo.Type, column.IsNullable), nativeTypeInfo.NativeType, column.IsNullable, nativeTypeInfo.Length, nativeTypeInfo.Precision, nativeTypeInfo.Scale);
            var finalTypeInfo = GetStorageTypeInfo(typeInfo, extractedConnectedColumn, column);

            var defaultValue         = GetColumnDefaultValue(column, finalTypeInfo);
            var defaultSqlExpression = GetColumnDefaultSqlExpression(column);

            if (column.IsSystem && column.Field.IsTypeId)
            {
                var type = column.Field.ReflectedType;
                if (type.IsEntity && type == type.Hierarchy.Root)
                {
                    defaultValue = typeIdProvider.GetTypeId(type.UnderlyingType);
                }
            }
            return(new StorageColumnInfo(currentTable, column.Name, finalTypeInfo)
            {
                DefaultValue = defaultValue,
                DefaultSqlExpression = defaultSqlExpression
            });
        }
Пример #13
0
        public void ShowPage(PageType type, string [] warnings)
        {
            if (type == PageType.Setup)
            {
                Header      = "Welcome to SparkleShare!";
                Description = "First off, what’s your name and email?\n(visible only to team members)";

                Table table = new Table(2, 3, true)
                {
                    RowSpacing    = 6,
                    ColumnSpacing = 6
                };

                Label name_label = new Label("<b>" + "Your Name:" + "</b>")
                {
                    UseMarkup = true,
                    Xalign    = 1
                };

                Entry name_entry = new Entry()
                {
                    Xalign           = 0,
                    ActivatesDefault = true
                };

                try {
                    UnixUserInfo user_info = UnixUserInfo.GetRealUser();

                    if (user_info != null && user_info.RealName != null)
                    {
                        // Some systems append a series of "," for some reason, TODO: Report upstream
                        name_entry.Text = user_info.RealName.TrimEnd(",".ToCharArray());
                    }
                } catch (ArgumentException) {
                    // No username, not a big deal
                }

                Entry email_entry = new Entry()
                {
                    Xalign           = 0,
                    ActivatesDefault = true
                };

                Label email_label = new Label("<b>" + "Email:" + "</b>")
                {
                    UseMarkup = true,
                    Xalign    = 1
                };

                table.Attach(name_label, 0, 1, 0, 1);
                table.Attach(name_entry, 1, 2, 0, 1);
                table.Attach(email_label, 0, 1, 1, 2);
                table.Attach(email_entry, 1, 2, 1, 2);

                VBox wrapper = new VBox(false, 9);
                wrapper.PackStart(table, true, false, 0);

                Button cancel_button   = new Button("Cancel");
                Button continue_button = new Button("Continue")
                {
                    Sensitive = false
                };


                Controller.UpdateSetupContinueButtonEvent += delegate(bool button_enabled) {
                    Application.Invoke(delegate { continue_button.Sensitive = button_enabled; });
                };

                name_entry.Changed    += delegate { Controller.CheckSetupPage(name_entry.Text, email_entry.Text); };
                email_entry.Changed   += delegate { Controller.CheckSetupPage(name_entry.Text, email_entry.Text); };
                cancel_button.Clicked += delegate { Controller.SetupPageCancelled(); };

                continue_button.Clicked += delegate {
                    Controller.SetupPageCompleted(name_entry.Text, email_entry.Text);
                };


                AddButton(cancel_button);
                AddButton(continue_button);
                Add(wrapper);

                Controller.CheckSetupPage(name_entry.Text, email_entry.Text);

                if (name_entry.Text.Equals(""))
                {
                    name_entry.GrabFocus();
                }
                else
                {
                    email_entry.GrabFocus();
                }
            }

            if (type == PageType.Add)
            {
                Header = "Where’s your project hosted?";

                VBox layout_vertical = new VBox(false, 16);
                HBox layout_fields   = new HBox(true, 32);
                VBox layout_address  = new VBox(true, 0);
                VBox layout_path     = new VBox(true, 0);

                ListStore store = new ListStore(typeof(string), typeof(Gdk.Pixbuf), typeof(string), typeof(Preset));

                SparkleTreeView tree_view = new SparkleTreeView(store)
                {
                    HeadersVisible = false,
                    SearchColumn   = -1,
                    EnableSearch   = false
                };

                ScrolledWindow scrolled_window = new ScrolledWindow()
                {
                    ShadowType = ShadowType.In
                };
                scrolled_window.SetPolicy(PolicyType.Never, PolicyType.Automatic);

                // Padding column
                tree_view.AppendColumn("Padding", new Gtk.CellRendererText(), "text", 0);
                tree_view.Columns [0].Cells [0].Xpad = 4;

                // Icon column
                tree_view.AppendColumn("Icon", new Gtk.CellRendererPixbuf(), "pixbuf", 1);
                tree_view.Columns [1].Cells [0].Xpad = 4;

                // Service column
                TreeViewColumn service_column = new TreeViewColumn()
                {
                    Title = "Service"
                };
                CellRendererText service_cell = new CellRendererText()
                {
                    Ypad = 8
                };
                service_column.PackStart(service_cell, true);
                service_column.SetCellDataFunc(service_cell, new TreeCellDataFunc(RenderServiceColumn));

                foreach (Preset preset in Controller.Presets)
                {
                    store.AppendValues("", new Gdk.Pixbuf(preset.ImagePath),
                                       "<span size=\"small\"><b>" + preset.Name + "</b>\n" +
                                       "<span fgcolor=\"" + SparkleShare.UI.SecondaryTextColor + "\">" + preset.Description + "</span>" +
                                       "</span>", preset);
                }

                tree_view.AppendColumn(service_column);
                scrolled_window.Add(tree_view);

                Entry address_entry = new Entry()
                {
                    Text             = Controller.PreviousAddress,
                    Sensitive        = (Controller.SelectedPreset.Address == null),
                    ActivatesDefault = true
                };

                Entry path_entry = new Entry()
                {
                    Text             = Controller.PreviousPath,
                    Sensitive        = (Controller.SelectedPreset.Path == null),
                    ActivatesDefault = true
                };

                tree_view.ButtonReleaseEvent += delegate {
                    path_entry.GrabFocus();
                };

                Label address_example = new Label()
                {
                    Xalign    = 0,
                    UseMarkup = true,
                    Markup    = "<span size=\"small\" fgcolor=\"" +
                                SparkleShare.UI.SecondaryTextColor + "\">" + Controller.SelectedPreset.AddressExample + "</span>"
                };

                Label path_example = new Label()
                {
                    Xalign    = 0,
                    UseMarkup = true,
                    Markup    = "<span size=\"small\" fgcolor=\"" +
                                SparkleShare.UI.SecondaryTextColor + "\">" + Controller.SelectedPreset.PathExample + "</span>"
                };


                TreeSelection default_selection = tree_view.Selection;
                TreePath      default_path      = new TreePath("" + Controller.SelectedPresetIndex);
                default_selection.SelectPath(default_path);

                tree_view.Model.Foreach(new TreeModelForeachFunc(
                                            delegate(ITreeModel model, TreePath path, TreeIter iter) {
                    string address;

                    try {
                        address = (model.GetValue(iter, 2) as Preset).Address;
                    } catch (NullReferenceException) {
                        address = "";
                    }

                    if (!string.IsNullOrEmpty(address) &&
                        address.Equals(Controller.PreviousAddress))
                    {
                        tree_view.SetCursor(path, service_column, false);
                        Preset preset = (Preset)model.GetValue(iter, 2);

                        if (preset.Address != null)
                        {
                            address_entry.Sensitive = false;
                        }

                        if (preset.Path != null)
                        {
                            path_entry.Sensitive = false;
                        }

                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                                            ));

                layout_address.PackStart(new Label()
                {
                    Markup = "<b>" + "Address" + "</b>",
                    Xalign = 0
                }, true, true, 0);

                layout_address.PackStart(address_entry, false, false, 0);
                layout_address.PackStart(address_example, false, false, 0);

                path_entry.Changed += delegate {
                    Controller.CheckAddPage(address_entry.Text, path_entry.Text, tree_view.SelectedRow);
                };

                layout_path.PackStart(new Label()
                {
                    Markup = "<b>" + "Remote Path" + "</b>",
                    Xalign = 0
                }, true, true, 0);

                layout_path.PackStart(path_entry, false, false, 0);
                layout_path.PackStart(path_example, false, false, 0);

                layout_fields.PackStart(layout_address, true, true, 0);
                layout_fields.PackStart(layout_path, true, true, 0);

                layout_vertical.PackStart(scrolled_window, true, true, 0);
                layout_vertical.PackStart(layout_fields, false, false, 0);

                tree_view.ScrollToCell(new TreePath("" + Controller.SelectedPresetIndex), null, true, 0, 0);

                Add(layout_vertical);


                if (string.IsNullOrEmpty(path_entry.Text))
                {
                    address_entry.GrabFocus();
                    address_entry.Position = -1;
                }
                else
                {
                    path_entry.GrabFocus();
                    path_entry.Position = -1;
                }

                Button cancel_button = new Button("Cancel");
                Button add_button    = new Button("Add")
                {
                    Sensitive = false
                };


                Controller.ChangeAddressFieldEvent += delegate(string text,
                                                               string example_text, FieldState state) {
                    Application.Invoke(delegate {
                        address_entry.Text      = text;
                        address_entry.Sensitive = (state == FieldState.Enabled);
                        address_example.Markup  = "<span size=\"small\" fgcolor=\"" +
                                                  SparkleShare.UI.SecondaryTextColor + "\">" + example_text + "</span>";
                    });
                };

                Controller.ChangePathFieldEvent += delegate(string text,
                                                            string example_text, FieldState state) {
                    Application.Invoke(delegate {
                        path_entry.Text      = text;
                        path_entry.Sensitive = (state == FieldState.Enabled);
                        path_example.Markup  = "<span size=\"small\" fgcolor=\""
                                               + SparkleShare.UI.SecondaryTextColor + "\">" + example_text + "</span>";
                    });
                };

                Controller.UpdateAddProjectButtonEvent += delegate(bool button_enabled) {
                    Application.Invoke(delegate { add_button.Sensitive = button_enabled; });
                };


                tree_view.CursorChanged += delegate(object sender, EventArgs e) {
                    Controller.SelectedPresetChanged(tree_view.SelectedRow);
                };

                address_entry.Changed += delegate {
                    Controller.CheckAddPage(address_entry.Text, path_entry.Text, tree_view.SelectedRow);
                };

                cancel_button.Clicked += delegate { Controller.PageCancelled(); };
                add_button.Clicked    += delegate { Controller.AddPageCompleted(address_entry.Text, path_entry.Text); };


                CheckButton check_button = new CheckButton("Fetch prior revisions")
                {
                    Active = false
                };
                check_button.Toggled += delegate { Controller.HistoryItemChanged(check_button.Active); };

                AddOption(check_button);
                AddButton(cancel_button);
                AddButton(add_button);

                Controller.HistoryItemChanged(check_button.Active);
                Controller.CheckAddPage(address_entry.Text, path_entry.Text, 1);
            }

            if (type == PageType.Invite)
            {
                Header      = "You’ve received an invite!";
                Description = "Do you want to add this project to SparkleShare?";

                Table table = new Table(2, 3, true)
                {
                    RowSpacing    = 6,
                    ColumnSpacing = 6
                };

                Label address_label = new Label("Address:")
                {
                    Xalign = 1
                };
                Label path_label = new Label("Remote Path:")
                {
                    Xalign = 1
                };

                Label address_value = new Label("<b>" + Controller.PendingInvite.Address + "</b>")
                {
                    UseMarkup = true,
                    Xalign    = 0
                };

                Label path_value = new Label("<b>" + Controller.PendingInvite.RemotePath + "</b>")
                {
                    UseMarkup = true,
                    Xalign    = 0
                };

                table.Attach(address_label, 0, 1, 0, 1);
                table.Attach(address_value, 1, 2, 0, 1);
                table.Attach(path_label, 0, 1, 1, 2);
                table.Attach(path_value, 1, 2, 1, 2);

                VBox wrapper = new VBox(false, 9);
                wrapper.PackStart(table, true, false, 0);

                Button cancel_button = new Button("Cancel");
                Button add_button    = new Button("Add");


                cancel_button.Clicked += delegate { Controller.PageCancelled(); };
                add_button.Clicked    += delegate { Controller.InvitePageCompleted(); };


                AddButton(cancel_button);
                AddButton(add_button);
                Add(wrapper);
            }

            if (type == PageType.Syncing)
            {
                Header      = String.Format("Adding project ‘{0}’…", Controller.SyncingFolder);
                Description = "This may take a while for large projects.\nIsn’t it coffee-o’clock?";

                ProgressBar progress_bar = new ProgressBar();
                progress_bar.Fraction = Controller.ProgressBarPercentage / 100;

                Button cancel_button = new Button()
                {
                    Label = "Cancel"
                };
                Button finish_button = new Button("Finish")
                {
                    Sensitive = false
                };

                Label progress_label = new Label("Preparing to fetch files…")
                {
                    Justify = Justification.Right,
                    Xalign  = 1
                };


                Controller.UpdateProgressBarEvent += delegate(double percentage, string speed) {
                    Application.Invoke(delegate {
                        progress_bar.Fraction = percentage / 100;
                        progress_label.Text   = speed;
                    });
                };

                cancel_button.Clicked += delegate { Controller.SyncingCancelled(); };


                VBox bar_wrapper = new VBox(false, 0);
                bar_wrapper.PackStart(progress_bar, false, false, 21);
                bar_wrapper.PackStart(progress_label, false, true, 0);

                Add(bar_wrapper);
                AddButton(cancel_button);
                AddButton(finish_button);
            }

            if (type == PageType.Error)
            {
                Header = "Oops! Something went wrong" + "…";

                VBox  points           = new VBox(false, 0);
                Image list_point_one   = new Image(UserInterfaceHelpers.GetIcon("list-point", 16));
                Image list_point_two   = new Image(UserInterfaceHelpers.GetIcon("list-point", 16));
                Image list_point_three = new Image(UserInterfaceHelpers.GetIcon("list-point", 16));

                Label label_one = new Label()
                {
                    Markup = "<b>" + Controller.PreviousUrl + "</b> is the address we’ve compiled. " +
                             "Does this look alright?",
                    Wrap   = true,
                    Xalign = 0
                };

                Label label_two = new Label()
                {
                    Text   = "Is this computer’s Client ID known by the host?",
                    Wrap   = true,
                    Xalign = 0
                };

                points.PackStart(new Label("Please check the following:")
                {
                    Xalign = 0
                }, false, false, 6);

                HBox point_one = new HBox(false, 0);
                point_one.PackStart(list_point_one, false, false, 0);
                point_one.PackStart(label_one, true, true, 12);
                points.PackStart(point_one, false, false, 12);

                HBox point_two = new HBox(false, 0);
                point_two.PackStart(list_point_two, false, false, 0);
                point_two.PackStart(label_two, true, true, 12);
                points.PackStart(point_two, false, false, 12);

                if (warnings.Length > 0)
                {
                    string warnings_markup = "";

                    foreach (string warning in warnings)
                    {
                        warnings_markup += "\n<b>" + warning + "</b>";
                    }

                    Label label_three = new Label()
                    {
                        Markup = "Here’s the raw error message:" + warnings_markup,
                        Wrap   = true,
                        Xalign = 0
                    };

                    HBox point_three = new HBox(false, 0);
                    point_three.PackStart(list_point_three, false, false, 0);
                    point_three.PackStart(label_three, true, true, 12);
                    points.PackStart(point_three, false, false, 12);
                }

                points.PackStart(new Label(""), true, true, 0);

                Button cancel_button    = new Button("Cancel");
                Button try_again_button = new Button("Retry")
                {
                    Sensitive = true
                };


                cancel_button.Clicked    += delegate { Controller.PageCancelled(); };
                try_again_button.Clicked += delegate { Controller.ErrorPageCompleted(); };


                AddButton(cancel_button);
                AddButton(try_again_button);
                Add(points);
            }

            if (type == PageType.StorageSetup)
            {
                Header      = string.Format("Storage type for ‘{0}’", Controller.SyncingFolder);
                Description = "What type of storage would you like to use?";

                VBox layout_vertical      = new VBox(false, 0);
                VBox layout_radio_buttons = new VBox(false, 0)
                {
                    BorderWidth = 12
                };

                foreach (StorageTypeInfo storage_type in SparkleShare.Controller.FetcherAvailableStorageTypes)
                {
                    RadioButton radio_button = new RadioButton(null,
                                                               storage_type.Name + "\n" + storage_type.Description);

                    (radio_button.Child as Label).Markup = string.Format(
                        "<b>{0}</b>\n<span fgcolor=\"{1}\">{2}</span>",
                        storage_type.Name, SparkleShare.UI.SecondaryTextColor, storage_type.Description);

                    (radio_button.Child as Label).Xpad = 9;

                    layout_radio_buttons.PackStart(radio_button, false, false, 9);
                    radio_button.Group = (layout_radio_buttons.Children [0] as RadioButton).Group;
                }

                layout_vertical.PackStart(new Label(""), true, true, 0);
                layout_vertical.PackStart(layout_radio_buttons, false, false, 0);
                layout_vertical.PackStart(new Label(""), true, true, 0);
                Add(layout_vertical);

                Button cancel_button   = new Button("Cancel");
                Button continue_button = new Button("Continue");

                continue_button.Clicked += delegate {
                    int checkbox_index = 0;
                    foreach (RadioButton radio_button in layout_radio_buttons.Children)
                    {
                        if (radio_button.Active)
                        {
                            StorageTypeInfo selected_storage_type = SparkleShare.Controller.FetcherAvailableStorageTypes [checkbox_index];
                            Controller.StoragePageCompleted(selected_storage_type.Type);
                            return;
                        }

                        checkbox_index++;
                    }
                };

                cancel_button.Clicked += delegate {
                    Controller.SyncingCancelled();
                };

                AddButton(cancel_button);
                AddButton(continue_button);
            }

            if (type == PageType.CryptoSetup || type == PageType.CryptoPassword)
            {
                if (type == PageType.CryptoSetup)
                {
                    Header      = string.Format("Encryption password for ‘{0}’", Controller.SyncingFolder);
                    Description = "Please a provide a strong password that you don’t use elsewhere.";
                }
                else
                {
                    Header      = string.Format("‘{0}’ contains encrypted files", Controller.SyncingFolder);
                    Description = "Please enter the password to see their contents.";
                }

                Label password_label = new Label("<b>" + "Password" + "</b>")
                {
                    UseMarkup = true,
                    Xalign    = 1
                };

                Entry password_entry = new Entry()
                {
                    Xalign           = 0,
                    Visibility       = false,
                    ActivatesDefault = true
                };

                CheckButton show_password_check_button = new CheckButton("Make visible")
                {
                    Active = false,
                    Xalign = 0,
                };

                Table table = new Table(2, 3, true)
                {
                    RowSpacing    = 6,
                    ColumnSpacing = 6
                };

                table.Attach(password_label, 0, 1, 0, 1);
                table.Attach(password_entry, 1, 2, 0, 1);

                table.Attach(show_password_check_button, 1, 2, 1, 2);

                VBox wrapper = new VBox(false, 9);
                wrapper.PackStart(table, true, false, 0);

                Image warning_image = new Image(
                    UserInterfaceHelpers.GetIcon("dialog-information", 24));

                Label warning_label = new Label()
                {
                    Xalign = 0,
                    Wrap   = true,
                    Text   = "This password can’t be changed later, and your files can’t be recovered if it’s forgotten."
                };

                HBox warning_layout = new HBox(false, 0);
                warning_layout.PackStart(warning_image, false, false, 15);
                warning_layout.PackStart(warning_label, true, true, 0);

                VBox warning_wrapper = new VBox(false, 0);
                warning_wrapper.PackStart(warning_layout, false, false, 15);

                if (type == PageType.CryptoSetup)
                {
                    wrapper.PackStart(warning_wrapper, false, false, 0);
                }

                Button cancel_button   = new Button("Cancel");
                Button continue_button = new Button("Continue")
                {
                    Sensitive = false
                };


                Controller.UpdateCryptoSetupContinueButtonEvent += delegate(bool button_enabled) {
                    Application.Invoke(delegate { continue_button.Sensitive = button_enabled; });
                };

                Controller.UpdateCryptoPasswordContinueButtonEvent += delegate(bool button_enabled) {
                    Application.Invoke(delegate { continue_button.Sensitive = button_enabled; });
                };

                show_password_check_button.Toggled += delegate {
                    password_entry.Visibility = !password_entry.Visibility;
                };

                password_entry.Changed += delegate {
                    if (type == PageType.CryptoSetup)
                    {
                        Controller.CheckCryptoSetupPage(password_entry.Text);
                    }
                    else
                    {
                        Controller.CheckCryptoPasswordPage(password_entry.Text);
                    }
                };

                cancel_button.Clicked += delegate { Controller.CryptoPageCancelled(); };

                continue_button.Clicked += delegate {
                    if (type == PageType.CryptoSetup)
                    {
                        Controller.CryptoSetupPageCompleted(password_entry.Text);
                    }
                    else
                    {
                        Controller.CryptoPasswordPageCompleted(password_entry.Text);
                    }
                };


                Add(wrapper);

                AddButton(cancel_button);
                AddButton(continue_button);

                password_entry.GrabFocus();
            }

            if (type == PageType.Finished)
            {
                Header      = "Your shared project is ready!";
                Description = "You can find the files in your SparkleShare folder.";

                UrgencyHint = true;

                Button show_files_button = new Button("Show Files");
                Button finish_button     = new Button("Finish");


                show_files_button.Clicked += delegate { Controller.ShowFilesClicked(); };
                finish_button.Clicked     += delegate { Controller.FinishPageCompleted(); };


                if (warnings.Length > 0)
                {
                    Image warning_image = new Image(UserInterfaceHelpers.GetIcon("dialog-information", 24));

                    Label warning_label = new Label(warnings [0])
                    {
                        Xalign = 0,
                        Wrap   = true
                    };

                    HBox warning_layout = new HBox(false, 0);
                    warning_layout.PackStart(warning_image, false, false, 15);
                    warning_layout.PackStart(warning_label, true, true, 0);

                    VBox warning_wrapper = new VBox(false, 0);
                    warning_wrapper.PackStart(warning_layout, false, false, 0);

                    Add(warning_wrapper);
                }
                else
                {
                    Add(null);
                }

                AddButton(show_files_button);
                AddButton(finish_button);
            }
        }
Пример #14
0
        public void ShowPage(PageType type, string [] warnings)
        {
            if (type == PageType.Setup)
            {
                Header      = "Welcome to SparkleShare!";
                Description = "First off, what’s your name and email?\n(visible only to team members)";

                FullNameLabel       = new SparkleLabel("Full Name:", NSTextAlignment.Right);
                FullNameLabel.Frame = new CGRect(165, Frame.Height - 234, 160, 17);

                FullNameTextField = new NSTextField()
                {
                    Frame       = new CGRect(330, Frame.Height - 238, 196, 22),
                    StringValue = new NSProcessInfo().GetFullUserName(),
                    Delegate    = new SparkleTextFieldDelegate()
                };

                EmailLabel       = new SparkleLabel("Email:", NSTextAlignment.Right);
                EmailLabel.Frame = new CGRect(165, Frame.Height - 264, 160, 17);

                EmailTextField = new NSTextField()
                {
                    Frame    = new CGRect(330, Frame.Height - 268, 196, 22),
                    Delegate = new SparkleTextFieldDelegate()
                };

                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };

                ContinueButton = new NSButton()
                {
                    Title   = "Continue",
                    Enabled = false
                };


                (FullNameTextField.Delegate as SparkleTextFieldDelegate).StringValueChanged += delegate {
                    Controller.CheckSetupPage(FullNameTextField.StringValue, EmailTextField.StringValue);
                };

                (EmailTextField.Delegate as SparkleTextFieldDelegate).StringValueChanged += delegate {
                    Controller.CheckSetupPage(FullNameTextField.StringValue, EmailTextField.StringValue);
                };

                ContinueButton.Activated += delegate {
                    string full_name = FullNameTextField.StringValue.Trim();
                    string email     = EmailTextField.StringValue.Trim();

                    Controller.SetupPageCompleted(full_name, email);
                };

                CancelButton.Activated += delegate { Controller.SetupPageCancelled(); };

                Controller.UpdateSetupContinueButtonEvent += delegate(bool button_enabled) {
                    SparkleShare.Controller.Invoke(() => {
                        ContinueButton.Enabled = button_enabled;
                    });
                };


                ContentView.AddSubview(FullNameLabel);
                ContentView.AddSubview(FullNameTextField);
                ContentView.AddSubview(EmailLabel);
                ContentView.AddSubview(EmailTextField);

                Buttons.Add(ContinueButton);
                Buttons.Add(CancelButton);

                Controller.CheckSetupPage(FullNameTextField.StringValue, EmailTextField.StringValue);

                if (FullNameTextField.StringValue.Equals(""))
                {
                    MakeFirstResponder((NSResponder)FullNameTextField);
                }
                else
                {
                    MakeFirstResponder((NSResponder)EmailTextField);
                }
            }

            if (type == PageType.Invite)
            {
                Header      = "You’ve received an invite!";
                Description = "Do you want to add this project to SparkleShare?";

                AddressLabel       = new SparkleLabel("Address:", NSTextAlignment.Right);
                AddressLabel.Frame = new CGRect(165, Frame.Height - 238, 160, 17);
                AddressLabel.Font  = NSFont.BoldSystemFontOfSize(12);

                AddressTextField = new SparkleLabel(Controller.PendingInvite.Address, NSTextAlignment.Left)
                {
                    Frame = new CGRect(330, Frame.Height - 240, 260, 17)
                };

                PathLabel       = new SparkleLabel("Remote Path:", NSTextAlignment.Right);
                PathLabel.Frame = new CGRect(165, Frame.Height - 262, 160, 17);
                PathLabel.Font  = NSFont.BoldSystemFontOfSize(12);

                PathTextField = new SparkleLabel(Controller.PendingInvite.RemotePath, NSTextAlignment.Left)
                {
                    Frame = new CGRect(330, Frame.Height - 264, 260, 17)
                };

                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };
                AddButton = new NSButton()
                {
                    Title = "Add"
                };


                CancelButton.Activated += delegate { Controller.PageCancelled(); };
                AddButton.Activated    += delegate { Controller.InvitePageCompleted(); };


                ContentView.AddSubview(AddressLabel);
                ContentView.AddSubview(PathLabel);
                ContentView.AddSubview(AddressTextField);
                ContentView.AddSubview(PathTextField);

                Buttons.Add(AddButton);
                Buttons.Add(CancelButton);
            }

            if (type == PageType.Add)
            {
                Header      = "Where’s your project hosted?";
                Description = "";

                AddressLabel = new SparkleLabel("Address:", NSTextAlignment.Left)
                {
                    Frame = new CGRect(190, Frame.Height - 310, 160, 17),
                    Font  = NSFont.BoldSystemFontOfSize(12)
                };

                AddressTextField = new NSTextField()
                {
                    Frame       = new CGRect(190, Frame.Height - 336, 196, 22),
                    Enabled     = (Controller.SelectedPreset.Address == null),
                    Delegate    = new SparkleTextFieldDelegate(),
                    StringValue = "" + Controller.PreviousAddress
                };

                AddressTextField.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;

                PathLabel = new SparkleLabel("Remote Path:", NSTextAlignment.Left)
                {
                    Frame = new CGRect(190 + 196 + 16, Frame.Height - 310, 160, 17),
                    Font  = NSFont.BoldSystemFontOfSize(12)
                };

                PathTextField = new NSTextField()
                {
                    Frame       = new CGRect(190 + 196 + 16, Frame.Height - 336, 196, 22),
                    Enabled     = (Controller.SelectedPreset.Path == null),
                    Delegate    = new SparkleTextFieldDelegate(),
                    StringValue = "" + Controller.PreviousPath
                };

                PathTextField.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;

                PathHelpLabel = new SparkleLabel(Controller.SelectedPreset.PathExample, NSTextAlignment.Left)
                {
                    TextColor = NSColor.DisabledControlText,
                    Frame     = new CGRect(190 + 196 + 16, Frame.Height - 358, 204, 19)
                };

                AddressHelpLabel = new SparkleLabel(Controller.SelectedPreset.AddressExample, NSTextAlignment.Left)
                {
                    TextColor = NSColor.DisabledControlText,
                    Frame     = new CGRect(190, Frame.Height - 358, 204, 19)
                };

                if (TableView == null || TableView.RowCount != Controller.Presets.Count)
                {
                    TableView = new NSTableView()
                    {
                        Frame            = new CGRect(0, 0, 0, 0),
                        RowHeight        = 38,
                        IntercellSpacing = new CGSize(8, 12),
                        HeaderView       = null,
                        Delegate         = new SparkleTableViewDelegate()
                    };

                    ScrollView = new NSScrollView()
                    {
                        Frame               = new CGRect(190, Frame.Height - 280, 408, 185),
                        DocumentView        = TableView,
                        HasVerticalScroller = true,
                        BorderType          = NSBorderType.BezelBorder
                    };

                    IconColumn = new NSTableColumn()
                    {
                        Width         = 36,
                        HeaderToolTip = "Icon",
                        DataCell      = new NSImageCell()
                        {
                            ImageAlignment = NSImageAlignment.Right
                        }
                    };

                    DescriptionColumn = new NSTableColumn()
                    {
                        Width         = 350,
                        HeaderToolTip = "Description",
                        Editable      = false
                    };

                    TableView.AddColumn(IconColumn);
                    TableView.AddColumn(DescriptionColumn);

                    // Hi-res display support was added after Snow Leopard
                    if (Environment.OSVersion.Version.Major < 11)
                    {
                        DataSource = new SparkleDataSource(1, Controller.Presets);
                    }
                    else
                    {
                        DataSource = new SparkleDataSource((float)BackingScaleFactor, Controller.Presets);
                    }

                    TableView.DataSource = DataSource;
                    TableView.ReloadData();

                    (TableView.Delegate as SparkleTableViewDelegate).SelectionChanged += delegate {
                        Controller.SelectedPresetChanged((int)TableView.SelectedRow);
                        Controller.CheckAddPage(AddressTextField.StringValue, PathTextField.StringValue, (int)TableView.SelectedRow);
                    };
                }

                TableView.SelectRow(Controller.SelectedPresetIndex, byExtendingSelection: false);
                TableView.ScrollRowToVisible(Controller.SelectedPresetIndex);
                MakeFirstResponder((NSResponder)TableView);

                HistoryCheckButton = new NSButton()
                {
                    Frame = new CGRect(190, Frame.Height - 400, 300, 18),
                    Title = "Fetch prior revisions"
                };

                if (Controller.FetchPriorHistory)
                {
                    HistoryCheckButton.State = NSCellStateValue.On;
                }

                HistoryCheckButton.SetButtonType(NSButtonType.Switch);

                AddButton = new NSButton()
                {
                    Title   = "Add",
                    Enabled = false
                };

                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };


                Controller.ChangeAddressFieldEvent += delegate(string text, string example_text, FieldState state) {
                    SparkleShare.Controller.Invoke(() => {
                        AddressTextField.StringValue = text;
                        AddressTextField.Enabled     = (state == FieldState.Enabled);
                        AddressHelpLabel.StringValue = example_text;
                    });
                };

                Controller.ChangePathFieldEvent += delegate(string text, string example_text, FieldState state) {
                    SparkleShare.Controller.Invoke(() => {
                        PathTextField.StringValue = text;
                        PathTextField.Enabled     = (state == FieldState.Enabled);
                        PathHelpLabel.StringValue = example_text;
                    });
                };


                (AddressTextField.Delegate as SparkleTextFieldDelegate).StringValueChanged += delegate {
                    Controller.CheckAddPage(AddressTextField.StringValue, PathTextField.StringValue, (int)TableView.SelectedRow);
                };

                (PathTextField.Delegate as SparkleTextFieldDelegate).StringValueChanged += delegate {
                    Controller.CheckAddPage(AddressTextField.StringValue, PathTextField.StringValue, (int)TableView.SelectedRow);
                };


                HistoryCheckButton.Activated += delegate {
                    Controller.HistoryItemChanged(HistoryCheckButton.State == NSCellStateValue.On);
                };

                AddButton.Activated += delegate {
                    Controller.AddPageCompleted(AddressTextField.StringValue, PathTextField.StringValue);
                };

                CancelButton.Activated += delegate { Controller.PageCancelled(); };

                Controller.UpdateAddProjectButtonEvent += delegate(bool button_enabled) {
                    SparkleShare.Controller.Invoke(() => {
                        AddButton.Enabled = button_enabled;
                    });
                };

                ContentView.AddSubview(ScrollView);
                ContentView.AddSubview(AddressLabel);
                ContentView.AddSubview(AddressTextField);
                ContentView.AddSubview(AddressHelpLabel);
                ContentView.AddSubview(PathLabel);
                ContentView.AddSubview(PathTextField);
                ContentView.AddSubview(PathHelpLabel);
                ContentView.AddSubview(HistoryCheckButton);

                Buttons.Add(AddButton);
                Buttons.Add(CancelButton);

                Controller.CheckAddPage(AddressTextField.StringValue, PathTextField.StringValue, (int)TableView.SelectedRow);
            }

            if (type == PageType.Syncing)
            {
                Header      = "Adding project ‘" + Controller.SyncingFolder + "’…";
                Description = "This may take a while for large projects.\nIsn’t it coffee-o’clock?";

                ProgressIndicator = new NSProgressIndicator()
                {
                    Frame         = new CGRect(190, Frame.Height - 200, 640 - 150 - 80, 20),
                    Style         = NSProgressIndicatorStyle.Bar,
                    MinValue      = 0.0,
                    MaxValue      = 100.0,
                    Indeterminate = false,
                    DoubleValue   = Controller.ProgressBarPercentage
                };

                ProgressIndicator.StartAnimation(this);

                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };

                FinishButton = new NSButton()
                {
                    Title   = "Finish",
                    Enabled = false
                };

                ProgressLabel       = new SparkleLabel("Preparing to fetch files…", NSTextAlignment.Right);
                ProgressLabel.Frame = new CGRect(Frame.Width - 40 - 250, 185, 250, 25);


                Controller.UpdateProgressBarEvent += delegate(double percentage, string speed) {
                    SparkleShare.Controller.Invoke(() => {
                        ProgressIndicator.DoubleValue = percentage;
                        ProgressLabel.StringValue     = speed;
                    });
                };


                CancelButton.Activated += delegate { Controller.SyncingCancelled(); };


                ContentView.AddSubview(ProgressLabel);
                ContentView.AddSubview(ProgressIndicator);

                Buttons.Add(FinishButton);
                Buttons.Add(CancelButton);
            }

            if (type == PageType.Error)
            {
                Header      = "Oops! Something went wrong…";
                Description = "Please check the following:";

                // Displaying marked up text with Cocoa is
                // a pain, so we just use a webview instead
                WebView web_view = new WebView();
                web_view.Frame = new CGRect(190, Frame.Height - 525, 375, 400);

                string html = "<style>" +
                              "* {" +
                              "  font-family: -apple-system, '" + UserInterface.FontName + "';" +
                              "  font-size: 12px; cursor: default;" +
                              "}" +
                              "body {" +
                              "  -webkit-user-select: none;" +
                              "  margin: 0;" +
                              "  padding: 3px;" +
                              "}" +
                              "li {" +
                              "  margin-bottom: 16px;" +
                              "  margin-left: 0;" +
                              "  padding-left: 0;" +
                              "  line-height: 20px;" +
                              "  word-wrap: break-word;" +
                              "}" +
                              "ul {" +
                              "  padding-left: 24px;" +
                              "}" +
                              "</style>" +
                              "<ul>" +
                              "  <li><b>" + Controller.PreviousUrl + "</b> is the address we’ve compiled. Does this look alright?</li>" +
                              "  <li>Is this computer’s Client ID known by the host?</li>" +
                              "</ul>";

                if (warnings.Length > 0)
                {
                    string warnings_markup = "";

                    foreach (string warning in warnings)
                    {
                        warnings_markup += "<br><b>" + warning + "</b>";
                    }

                    html = html.Replace("</ul>", "<li>Here’s the raw error message: " + warnings_markup + "</li></ul>");
                }

                web_view.MainFrame.LoadHtmlString(html, new NSUrl(""));
                web_view.DrawsBackground = false;

                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };
                TryAgainButton = new NSButton()
                {
                    Title = "Retry"
                };


                CancelButton.Activated   += delegate { Controller.PageCancelled(); };
                TryAgainButton.Activated += delegate { Controller.ErrorPageCompleted(); };


                ContentView.AddSubview(web_view);

                Buttons.Add(TryAgainButton);
                Buttons.Add(CancelButton);
            }

            if (type == PageType.StorageSetup)
            {
                Header      = string.Format("Storage type for ‘{0}’", Controller.SyncingFolder);
                Description = "What type of storage would you like to use?";


                storage_type_descriptions = new List <NSTextField> ();

                ButtonCellProto = new NSButtonCell();
                ButtonCellProto.SetButtonType(NSButtonType.Radio);
                ButtonCellProto.Font = NSFont.BoldSystemFontOfSize(12);

                Matrix = new NSMatrix(new CGRect(202, Frame.Height - 256 - 128, 256, 256), NSMatrixMode.Radio,
                                      ButtonCellProto, SparkleShare.Controller.FetcherAvailableStorageTypes.Count, 1);

                Matrix.CellSize         = new CGSize(256, 36);
                Matrix.IntercellSpacing = new CGSize(32, 32);

                int i = 0;
                foreach (StorageTypeInfo storage_type in SparkleShare.Controller.FetcherAvailableStorageTypes)
                {
                    Matrix.Cells [i].Title = " " + storage_type.Name;

                    NSTextField storage_type_description = new SparkleLabel(storage_type.Description, NSTextAlignment.Left)
                    {
                        TextColor = NSColor.DisabledControlText,
                        Frame     = new CGRect(223, Frame.Height - 190 - (68 * i), 256, 32)
                    };

                    storage_type_descriptions.Add(storage_type_description);
                    ContentView.AddSubview(storage_type_description);

                    i++;
                }

                ContentView.AddSubview(Matrix);


                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };
                ContinueButton = new NSButton()
                {
                    Title = "Continue"
                };

                ContinueButton.Activated += delegate {
                    StorageTypeInfo selected_storage_type = SparkleShare.Controller.FetcherAvailableStorageTypes [(int)Matrix.SelectedRow];
                    Controller.StoragePageCompleted(selected_storage_type.Type);
                };

                CancelButton.Activated += delegate { Controller.SyncingCancelled(); };

                Buttons.Add(ContinueButton);
                Buttons.Add(CancelButton);


                NSApplication.SharedApplication.RequestUserAttention(NSRequestUserAttentionType.CriticalRequest);
            }

            if (type == PageType.CryptoSetup || type == PageType.CryptoPassword)
            {
                if (type == PageType.CryptoSetup)
                {
                    Header      = "Set up file encryption";
                    Description = "Please a provide a strong password that you don’t use elsewhere.";
                }
                else
                {
                    Header      = "This project contains encrypted files";
                    Description = "Please enter the password to see their contents.";
                }

                int extra_pos_y = 0;

                if (type == PageType.CryptoPassword)
                {
                    extra_pos_y = 20;
                }

                PasswordLabel = new SparkleLabel("Password:"******"Show password",
                    State = NSCellStateValue.Off
                };

                ShowPasswordCheckButton.SetButtonType(NSButtonType.Switch);

                WarningImage      = NSImage.ImageNamed("NSInfo");
                WarningImage.Size = new CGSize(24, 24);

                WarningImageView = new NSImageView()
                {
                    Image = WarningImage,
                    Frame = new CGRect(200, Frame.Height - 320, 24, 24)
                };

                WarningTextField = new SparkleLabel("This password can’t be changed later, and your files can’t be recovered if it’s forgotten.", NSTextAlignment.Left)
                {
                    Frame = new CGRect(235, Frame.Height - 390, 325, 100),
                };

                CancelButton = new NSButton()
                {
                    Title = "Cancel"
                };

                ContinueButton = new NSButton()
                {
                    Title   = "Continue",
                    Enabled = false
                };


                Controller.UpdateCryptoPasswordContinueButtonEvent += delegate(bool button_enabled) {
                    SparkleShare.Controller.Invoke(() => { ContinueButton.Enabled = button_enabled; });
                };

                Controller.UpdateCryptoSetupContinueButtonEvent += delegate(bool button_enabled) {
                    SparkleShare.Controller.Invoke(() => { ContinueButton.Enabled = button_enabled; });
                };

                ShowPasswordCheckButton.Activated += delegate {
                    if (PasswordTextField.Superview == ContentView)
                    {
                        PasswordTextField.RemoveFromSuperview();
                        ContentView.AddSubview(VisiblePasswordTextField);
                    }
                    else
                    {
                        VisiblePasswordTextField.RemoveFromSuperview();
                        ContentView.AddSubview(PasswordTextField);
                    }
                };

                (PasswordTextField.Delegate as SparkleTextFieldDelegate).StringValueChanged += delegate {
                    VisiblePasswordTextField.StringValue = PasswordTextField.StringValue;

                    if (type == PageType.CryptoSetup)
                    {
                        Controller.CheckCryptoSetupPage(PasswordTextField.StringValue);
                    }
                    else
                    {
                        Controller.CheckCryptoPasswordPage(PasswordTextField.StringValue);
                    }
                };

                (VisiblePasswordTextField.Delegate as SparkleTextFieldDelegate).StringValueChanged += delegate {
                    PasswordTextField.StringValue = VisiblePasswordTextField.StringValue;

                    if (type == PageType.CryptoSetup)
                    {
                        Controller.CheckCryptoSetupPage(PasswordTextField.StringValue);
                    }
                    else
                    {
                        Controller.CheckCryptoPasswordPage(PasswordTextField.StringValue);
                    }
                };

                ContinueButton.Activated += delegate {
                    if (type == PageType.CryptoSetup)
                    {
                        Controller.CryptoSetupPageCompleted(PasswordTextField.StringValue);
                    }
                    else
                    {
                        Controller.CryptoPasswordPageCompleted(PasswordTextField.StringValue);
                    }
                };

                CancelButton.Activated += delegate { Controller.CryptoPageCancelled(); };


                ContentView.AddSubview(PasswordLabel);
                ContentView.AddSubview(PasswordTextField);
                ContentView.AddSubview(ShowPasswordCheckButton);

                if (type == PageType.CryptoSetup)
                {
                    ContentView.AddSubview(WarningImageView);
                    ContentView.AddSubview(WarningTextField);
                }

                Buttons.Add(ContinueButton);
                Buttons.Add(CancelButton);

                MakeFirstResponder((NSResponder)PasswordTextField);
                NSApplication.SharedApplication.RequestUserAttention(NSRequestUserAttentionType.CriticalRequest);
            }


            if (type == PageType.Finished)
            {
                Header      = "Your shared project is ready!";
                Description = "You can find the files in your SparkleShare folder.";

                if (warnings.Length > 0)
                {
                    WarningImage      = NSImage.ImageNamed("NSInfo");
                    WarningImage.Size = new CGSize(24, 24);

                    WarningImageView = new NSImageView()
                    {
                        Image = WarningImage,
                        Frame = new CGRect(200, Frame.Height - 175, 24, 24)
                    };

                    WarningTextField       = new SparkleLabel(warnings [0], NSTextAlignment.Left);
                    WarningTextField.Frame = new CGRect(235, Frame.Height - 245, 325, 100);

                    ContentView.AddSubview(WarningImageView);
                    ContentView.AddSubview(WarningTextField);
                }

                ShowFilesButton = new NSButton()
                {
                    Title = "Show Files"
                };
                FinishButton = new NSButton()
                {
                    Title = "Finish"
                };


                ShowFilesButton.Activated += delegate { Controller.ShowFilesClicked(); };
                FinishButton.Activated    += delegate { Controller.FinishPageCompleted(); };


                Buttons.Add(FinishButton);
                Buttons.Add(ShowFilesButton);

                NSApplication.SharedApplication.RequestUserAttention(NSRequestUserAttentionType.CriticalRequest);
            }
        }
 private static bool CheckScaleAndPrecision(StorageTypeInfo from, StorageTypeInfo to)
 {
     return(LessOrEqual(from.Scale, to.Scale) && LessOrEqual(from.Precision, to.Precision));
 }