ReMake Posted October 1, 2021 Share Posted October 1, 2021 It's a simple interface and a CodeLab script for it. Spoiler // Name:Color // Submenu: // Author: // Title: // Version: // Desc: // Keywords: // URL: // Help: #region UICode ListBoxControl Mode = 0; // {!Gray} Color|None|Primary|Secondary|Custom ColorWheelControl CustomColor = ColorBgra.FromBgr(0, 60, 120); // [!] {!Gray} CheckboxControl Gray = false; // Grayscale #endregion void Render(Surface dst, Surface src, Rectangle rect) { ColorBgra currentPixel; for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { currentPixel = src[x,y]; dst[x,y] = currentPixel; } } } Both controls (drop-down list and color wheel) active until the Grayscale checkbox is selected. This is easy to do in CodeLab. But I need the color wheel to be active only when the Custom item is selected in the drop-down list. The solution seems simple - add the rule IndirectUI 'ReadOnlyBoundToValueRule' in VS project. Spoiler public enum PropertyNames { Mode, CustomColor, Gray } public enum ModeOptions { None, Primary, Secondary, Custom } protected override PropertyCollection OnCreatePropertyCollection() { List<Property> props = new List<Property>(); props.Add(StaticListChoiceProperty.CreateForEnum<ModeOptions>(PropertyNames.Mode, 0, false)); props.Add(new Int32Property(PropertyNames.CustomColor, ColorBgra.ToOpaqueInt32(PrimaryColor), 0, 0xffffff)); props.Add(new BooleanProperty(PropertyNames.Gray, false)); List<PropertyCollectionRule> propRules = new List<PropertyCollectionRule>(); propRules.Add(new ReadOnlyBoundToBooleanRule(PropertyNames.Mode, PropertyNames.Gray, false)); propRules.Add(new ReadOnlyBoundToBooleanRule(PropertyNames.CustomColor, PropertyNames.Gray, false)); propRules.Add(new ReadOnlyBoundToValueRule<object, StaticListChoiceProperty>(PropertyNames.CustomColor, PropertyNames.Mode, ModeOptions.Custom, true)); return new PropertyCollection(props, propRules); } This works correctly until you check the Grayscale checkbox. If you have selected one of the first three items in the drop-down list, then after unchecking the Grayscale checkbox, the color wheel becomes active, although it should be active only when selecting the fourth item (Custom). Any suggestions? Quote Link to comment Share on other sites More sharing options...
Reptillian Posted October 1, 2021 Share Posted October 1, 2021 I haven't tested this, but if I have to wager a guess, it's because you're using multiple rules and IndirectUI doesn't address that too well. I have that bugs in few of my plugins, I can't fix that. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
Red ochre Posted October 1, 2021 Share Posted October 1, 2021 Perhaps MJW's code at the bottom of this thread is relevant. (I'm not great with the logic of these rules 😉). https://forums.getpaint.net/topic/22046-tutorial-how-to-use-indirectui-rules/ 1 Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings Link to comment Share on other sites More sharing options...
otuncelli Posted October 1, 2021 Share Posted October 1, 2021 Did you try ReadOnlyBoundToNameValuesRule? 1 1 Quote Link to comment Share on other sites More sharing options...
ReMake Posted October 1, 2021 Author Share Posted October 1, 2021 @Red ochre, @otuncelli, thank you for the answer. I will try to figure it out, although it is somewhat difficult for me. Quote Link to comment Share on other sites More sharing options...
MJW Posted October 1, 2021 Share Posted October 1, 2021 You are trying to activate a control based on two separate conditions, which is not easy to do. I believe the two conditions are treated entirely independently; they aren't logically combined. As I recall, it's simply the state of the last-changed conditional control that determines whether the control will be active. However, a comment by BoltBait suggests there's a way around this: Quote Administrator 14.1k California, USA Posted April 6, 2020 I'm no expert in IndirectUI rules. And, any time I need to make a complicated one I get a headache. But, this one's got me stumped. Along with other controls, I have 2 check boxes and a slider that I want to control this way: Box 1 - Box 2 - Slider [ ] [ ] Disabled [ X ] [ ] Enabled [ ] [ X ] Disabled [ X ] [ X ] Disabled As you can see, Box 2 is a kind of "override" and if it is checked, the slider is always disabled. I nearly have it working like this: propRules.Add(new ReadOnlyBoundToNameValuesRule(PropertyNames.Slider, false, new TupleStruct<object, object>[] { new TupleStruct<object, object>(PropertyNames.Box1, false), new TupleStruct<object, object>(PropertyNames.Box2, true) })); I say "nearly" because the default settings of the two boxes are unchecked and the slider always starts out enabled instead of disabled. Once you click either of the checkboxes the slider is en/disabled according to my design. However, I can not figure out how to get the slider to start out in the disabled state. I'm not sure if this is important or not, but I have an additional rule in place that controls the enabled/disabled state of Box 1: Box 2 - Box 1 [ ] Enabled [ X ] Disabled Code: propRules.Add(new ReadOnlyBoundToBooleanRule(PropertyNames.Box1, PropertyNames.Box2, false)); Of course, this is very simple and works fine. And, of course, I have several other rules controlling other sliders, etc. All of those rules are working fine. Can anyone help here? EDIT: From what I can tell, using "ReadOnlyBoundToNameValueRule" where the conditions would start out a control as disabled just doesn't work. Is this a bug in Paint.NET? Or, am I using the rules wrong? The solution to BoltBait;'s problem (which shows BoltBait's approach was essentially correct -- he just overlooked a detail): Quote null54 Members 1.3k Posted April 6, 2020 On 4/6/2020 at 4:19 PM, BoltBait said: I say "nearly" because the default settings of the two boxes are unchecked and the slider always starts out enabled instead of disabled. Once you click either of the checkboxes the slider is en/disabled according to my design. However, I can not figure out how to get the slider to start out in the disabled state. Are you setting the slider to readonly in the Int32Property constructor? new Int32Property(PropertyNames.Slider, defaultValue, minValue, maxValue, true) It's one of those things I always intended to read carefully and understand, but never got around to it. Perhaps someone (maybe even me) can do so, and write a tutorial on the matter. 1 1 Quote Link to comment Share on other sites More sharing options...
AndrewDavid Posted October 1, 2021 Share Posted October 1, 2021 (edited) This is new Never seen this before. From @MJW's post. Edited October 1, 2021 by AndrewDavid Removed Pic Quote (My New Signature) Nickpic was a image hosting source made specifically for RPers and its shutting down. I use postimage.IO for free web hosting. How long before they follow photobucket and NicKPic? Link to comment Share on other sites More sharing options...
Reptillian Posted October 1, 2021 Share Posted October 1, 2021 14 minutes ago, MJW said: one of those things I always intended to read carefully and understand, but never got around to it. Perhaps someone (maybe even me) can do so, and write a tutorial on the matter. I would appreciate that if you could. Also to anyone else that volunteer to this. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
midora Posted October 1, 2021 Share Posted October 1, 2021 @AndrewDavid This will happen if someone links to a group which is not public. Quote Link to comment Share on other sites More sharing options...
MJW Posted October 1, 2021 Share Posted October 1, 2021 Sorry about that. I didn't realize that wasn't in a public place. I don't know why it wasn't. I replaced the link with BoltBait's comment and Null54's followup comment . I hope that's okay with BoltBait, Null54, and the other administrators. 1 1 Quote Link to comment Share on other sites More sharing options...
MJW Posted October 1, 2021 Share Posted October 1, 2021 @otuncelli's link provides the answer (in a thread I'd somehow missed). ReadOnlyBoundToValueRule has a overload that accepts an array of conditions. The conditions can be from separate controls. Of course, this only works for VS projects, not for CodeLab. I believe @midora's problem mentioned in the last thread comment is probably the same as BoltBait's problem: if the default state of the conditioning controls would cause the conditioned control to be deactivated, the conditioned control needs to be initialized to a deactivated state. 1 Quote Link to comment Share on other sites More sharing options...
ReMake Posted October 1, 2021 Author Share Posted October 1, 2021 15 minutes ago, MJW said: Of course, this only works for VS projects, not for CodeLab. It is precisely because CodeLab cannot set two different dependencies for the same control that I am trying to solve this problem in VS. @MJW, thank you for your suggestions. Quote Link to comment Share on other sites More sharing options...
BoltBait Posted October 2, 2021 Share Posted October 2, 2021 6 hours ago, MJW said: I hope that's okay with BoltBait Sure, make me look like an idiot... IN PUBLIC! Quote Download: BoltBait's Plugin Pack | CodeLab | and a Computer Dominos Game Link to comment Share on other sites More sharing options...
MJW Posted October 2, 2021 Share Posted October 2, 2021 2 hours ago, BoltBait said: Sure, make me look like an idiot... IN PUBLIC! I thought it made you look pretty smart. Until I read your comment I had no idea there was a way to activate a control based on the state of two others. You just missed a minor detail about initializing the control. Quote Link to comment Share on other sites More sharing options...
BoltBait Posted October 2, 2021 Share Posted October 2, 2021 31 minutes ago, MJW said: You just missed a minor detail about initializing the control. Yeah, something I like to call a "rookie mistake!" Quote Download: BoltBait's Plugin Pack | CodeLab | and a Computer Dominos Game Link to comment Share on other sites More sharing options...
MJW Posted October 2, 2021 Share Posted October 2, 2021 I added a comment to the Indirect Rule Tutorial that briefly explains how the enable a control based on the state of more than one control. Quote Link to comment Share on other sites More sharing options...
ReMake Posted October 2, 2021 Author Share Posted October 2, 2021 12 hours ago, MJW said: I added a comment ... @MJW, thanks for the comment. I tried to apply ReadOnlyBoundToNameValuesRule: List<PropertyCollectionRule> propRules = new List<PropertyCollectionRule>(); propRules.Add(new ReadOnlyBoundToBooleanRule(PropertyNames.Mode, PropertyNames.Gray, false)); // propRules.Add(new ReadOnlyBoundToBooleanRule(PropertyNames.CustomColor, PropertyNames.Gray, false)); // propRules.Add(new ReadOnlyBoundToValueRule<object, StaticListChoiceProperty>(PropertyNames.CustomColor, PropertyNames.Mode, ModeOptions.Custom, true)); propRules.Add(new ReadOnlyBoundToNameValuesRule(PropertyNames.CustomColor, true, new TupleStruct<object, object>[] { new TupleStruct<object, object>(PropertyNames.Gray, false), new TupleStruct<object, object>(PropertyNames.Mode, ModeOptions.Custom) })); return new PropertyCollection(props, propRules); So far, this rule does not work for me. ReadOnlyBoundToNameValuesRule only works correctly with the Gray checkbox. The state of the CustomColor control is practically independent of the Mode drop-down list item. Probably the difficulties of language translation did not allow me to interpret your comment correctly. I have tried many options for writing the ReadOnlyBoundToNameValuesRule rule, but so far to no avail. Quote Link to comment Share on other sites More sharing options...
MJW Posted October 2, 2021 Share Posted October 2, 2021 2 hours ago, ReMake said: So far, this rule does not work for me. ReadOnlyBoundToNameValuesRule only works correctly with the Gray checkbox. The state of the CustomColor control is practically independent of the Mode drop-down list item. I don't know why the state of the CustomColor control would be practically independent of the Mode drop-down list item, but I don't think the logic of your call is quite right. What you have will enable the CustomColor control if either Gray is false OR Custom is selected. I think you want to enable it only if Gray is false AND Custom is selected. This is like the situation I mentioned in the Note, where you must disable the control if either Gray is true or any of the other modes is selected. EDIT: Also, don't overlook the little reminder that unless Custom is the default mode, you'll need to explicitly disable the colorwheel when you create it by setting the ReadOnly flag. Otherwise, it will initially be enabled even though it shouldn't be. Quote Link to comment Share on other sites More sharing options...
MJW Posted October 2, 2021 Share Posted October 2, 2021 14 hours ago, BoltBait said: Yeah, something I like to call a "rookie mistake!" I actually think it's a slight bug in the array version of ReadOnlyBoundToNameValuesRule. The simpler versions correctly initially disable a control based on the default value of the control it depends on. Or at least I've never encountered any problem with that. Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted October 2, 2021 Share Posted October 2, 2021 2 hours ago, MJW said: I actually think it's a slight bug in the array version of ReadOnlyBoundToNameValuesRule. The simpler versions correctly initially disable a control based on the default value of the control it depends on. Or at least I've never encountered any problem with that. If there's a bug, I'll need a repro so that I can fix it Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
MJW Posted October 2, 2021 Share Posted October 2, 2021 It's a pretty minor bug, it that's what it is, but it's easy to reproduce. Just use BoltBait's example I quoted above: propRules.Add(new ReadOnlyBoundToNameValuesRule(PropertyNames.Slider, false, new TupleStruct<object, object>[] { new TupleStruct<object, object>(PropertyNames.Box1, false), new TupleStruct<object, object>(PropertyNames.Box2, true) })); Despite that fact that the Slider control should initially be disabled because the default for Box2 is checked, it will be enabled unless it's initialized to ReadOnly. Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted October 3, 2021 Share Posted October 3, 2021 Okay I think I just fixed it for 4.3.2, the OnInitialized() method was just missing a call to Sync() 1 1 Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Rick Brewster Posted October 3, 2021 Share Posted October 3, 2021 18 hours ago, MJW said: propRules.Add(new ReadOnlyBoundToNameValuesRule(PropertyNames.Slider, false, new TupleStruct<object, object>[] { new TupleStruct<object, object>(PropertyNames.Box1, false), new TupleStruct<object, object>(PropertyNames.Box2, true) })); Also, you can use a simpler syntax for the tuples. I just added this support for 4.3.2 to do implicit conversions to-and-from regular ValueTuples: propRules.Add(new ReadOnlyBoundToNameValuesRule(PropertyNames.Slider, false, (PropertyNames.Box1, false), (PropertyNames.Box2, true) })); And because the array parameter is params, no need for the new ...[] { ... } boilerplate 1 2 Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
ReMake Posted October 5, 2021 Author Share Posted October 5, 2021 (edited) 10 hours ago, Rick Brewster said: Fixed ReadOnlyBoundToNameValuesRule for IndirectUI-based plugins. It was not initializing correctly, although it would work correctly afterward. Perhaps I am trying to achieve something unattainable, but in my opinion, the last change did not lead to a change in the behavior of the controls, which I described above in the first post. On the contrary, the Color Wheel is now always active regardless of the drop-down list item. Maybe I'm so stupid that I couldn't figure out the logic of Indirect UI rules. Can any of the developers give me an example of writing an IndirectUI rule that would allow the Color Wheel to be active if and only if the Custom item is selected in the drop-down list and the Gray checkbox is not checked? Edited October 5, 2021 by ReMake Quote Link to comment Share on other sites More sharing options...
midora Posted October 5, 2021 Share Posted October 5, 2021 You just have to do it step by step. So first you should think about the readonly conditions: Mode.Readonly = Gray CustomColor.Readonly = Gray || (Mode != CustomColor) We can not handle '!=' as far as I know so just rewrite the condition CustomColor.Readonly = Gray || (Mode == None) || (Mode == Primary) || (Mode == Secondary) Now create the rules List<PropertyCollectionRule> propRules = new List<PropertyCollectionRule>() { new ReadOnlyBoundToBooleanRule(PropertyNames.Mode, PropertyNames.Gray, false), new ReadOnlyBoundToNameValuesRule(PropertyNames.CustomColor, false, new TupleStruct<object, object>[] { new TupleStruct<object, object>(PropertyNames.Gray, true), new TupleStruct<object, object>(PropertyNames.Mode, ModeOptions.None), new TupleStruct<object, object>(PropertyNames.Mode, ModeOptions.Primary), new TupleStruct<object, object>(PropertyNames.Mode, ModeOptions.Secondary), }), }; or use the new syntax variant provided in 4.3.2 List<PropertyCollectionRule> propRules = new List<PropertyCollectionRule>() { new ReadOnlyBoundToBooleanRule(PropertyNames.Mode, PropertyNames.Gray, false), new ReadOnlyBoundToNameValuesRule(PropertyNames.CustomColor, false, (PropertyNames.Gray, true), (PropertyNames.Mode, ModeOptions.None), (PropertyNames.Mode, ModeOptions.Primary), (PropertyNames.Mode, ModeOptions.Secondary) ), }; 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.