I have 3 projects, (Ex. project1, project2, project3). Some parts of these projects are using just 1 Form (frmDetails) placed on a separate folder.
I want to Disable some details on my form depends on what project I open.
For example, I opened Project1 - all details on my form are displayed. Then when I opened project2 - I want "Age" and "Birthday" set Visible to false.
What functions that I need to this?
The easiest way to do that, is to make 3 separate copies of the form for 3 projects and modify them as needed.
If you wish, you could create a class from that form with minimal objects that appear in every project, and create 3 separate forms from that class per project.
Normally, after you build an executable, executable doesn't know from which project it was build. So you can't basically have one form behaving differently per project. However, per project you might add something that tells the project (be it a text, xml, Json, dbf ... file). So you could read that file's content in load or init of form and set form objects' visibility on\off if you want to do it with just a single form. It would make things harder and would be confusing but at the end it might sound 'nice' since it is only a single form. My suggestion, as said on top, create 3 separate copies per project. That way it is much easier to control them.
If you're using an application object, you can have a property of that object that identifies the project. However, I'd be more likely to do this in a more generic way that specifically looking at a single property.
You might use a set of logical properties that indicate options you can turn on and off, and then you can check those properties in your forms.
Related
Using Sphinx's domain-aware ObjectDescriptions I can create fancy rendered documentation for them. For example:
.. py:function:: pyfunc()
Describes a Python function.
This renders the content in a nice way, and this works really well with module indices, references and so on. Cool so far!
Now, let's say I have that directive in a source document src/mymodule/functions.rst, and I have a bunch of text in src/guide/getting-started.rst, I can reference to the objects like
:py:func:`pyfunc`
Also cool!
Now, my actual question; Could I also tell the Sphinx writer to re-render the same documentation snippet for that object? To ease the user in not having to navigating away from the Getting Started page where I just want to include a single piece of content again.
What I've tried to do:
Simply copy the contents. This results in a warning that the object is defined multiple times, hurts the index and as a result references don't point to the "authoritative" place in your project, if unlucky. Not okay.
Document each object in its own file and then use .. include:: rel/path/to/pyfunc.rst in each document where I want to render it. As those includes are literal on ReST-level, this results in the same downsides as the option above. :-(
Thus, I'm looking for a solution where I would tell the renderer/writer of Sphinx to simply re-render the contents of a reference instead of producing a link. It should not add it to the index for a simple re-render.
I'm okay with a custom extension or a domain-specific custom solution - I'm already using my own custom domain, but I just used the general Python domain above as a well-known example.
Context for the use case: I'm building a Protobuf domain. Protobuf messages and enums are reused a lot and I would like to show the context of commonly reused objects inline on pages where this is useful to the reader. This means it is repeated over the whole project on purpose where it is deemed useful rather than navigating away all the time. Yet only the reference page should be "authoritative".
I've been successful with a dirty hack: abusing the XRef role logic. Cross-references in Sphinx render dynamically (e.g. Table 23) by producing arbitrary 'nodes'. By:
keeping a copy of the parent node during parsing in a custom Domain
registering a custom Sphinx/ReST XRef role to render a whole set of nodes (the saved parent node)
re-running the ReferencesResolver another time
... this basically does what I need. But yuck, it's rather ugly.
Working example I implemented in a Protobuf Domain extension.
As per the documentation of Silverstripe, template inheritance is defined as follows:
mysite (or other name given to site folder)
module-specific themes (e.g. themes/simple_blog)
themes (e.g. themes/simple)
modules (e.g. blog)
framework
Now I've got a site that has quite a few different themes. Well, "different" in that they have different names, but they still got an awful lot in common. Now I am putting all the common files in the /mysite/templates folder, but that means that if one of my themes needs a change in one of the templates, I need to remove that file from the common folder, and move it to ALL the different theme folders. In this way I end up with a lot of duplicate templates.
In my case it would be beneficial to change the inheritance order, causing the specific theme folder to take precedence over the /mysite folder. In such a way I could just copy the template that has to be changed to the theme folder and that theme one will use the changed one, while the rest keeps using the generic one in the /mysite folder:
themes (e.g. themes/simple)
module-specific themes (e.g. themes/simple_blog)
mysite (or other name given to site folder)
modules (e.g. blog)
framework
It also seems to me to be the more obviuous way to do it, but I probably am missing some important point here. Nonetheless, would doing this be possible without hacking the core?
Template inheritance rendering seems to be managed by two classes predominantly, SSViewer (a core class for handling view rendering) and Controller (which all other controllers inherit from).
For view rendering, a SSViewer object can take an array in its constructor for template inheritance. This is important because the Controller class actually instantiates the SSViewer in a function called getViewer.
It is important to mention at this stage, a normal SilverStripe site you are normally inheriting from ContentController instead which overrides the getViewer of Controller. It won't really change too much of what you need to write but it is important depending how low-level you want this to apply.
For what you want to apply to pages in general, you would be looking at overriding getViewer in your Page_Controller. As for what specifically you would need to write, that is somewhat dependent on your entire site structure. I would imagine it would need to start off a little like this though:
public function getViewer($action) {
$viewer = Parent::getViewer($action);
$templates = $viewer->templates();
//Do your processing that you need to here
//Set it back via:
//$viewer->setTemplateFile($type, $file);
//Alternatively, you can create a new SSViewer object
return $viewer;
}
It will be a bit of experimentation to work out what exactly you need to do for shuffling around the data though this was never going to be easy. Once you start heading down this path, you likely will find a number of edge cases where this may not work properly (eg. template includes).
The question and the accepted answer are for SilverStripe 3, and should be referred to for queries relating to SilverStripe 3.x. The following refers to SilverStripe 4.
As SilverStripe 4 is currently the latest stable version and now sets theme inheritance instead of template inheritance, the question and answer may not be suitable for newer installations or up to date installations.
The best way to control inheritance in SilverStripe 4 is to ensure that the themes are configured in the correct order, and that the module inheritance is configured appropriately.
Your mysite/_config/theme.yml file typically declares the theme inheritance, and you should adjust this file to control theme inheritance appropriately. For modules, you need to specify the appropriate Before and After in your mycustommodule/_config/modules.yml file.
The following example is for a sile with both the mytheme and simple themes, a custom module without an _config/modules.yml file, and a vendor module without an _config/modules.yml file.
SilverStripe\View\SSViewer:
themes:
- 'mytheme'
- 'simple'
- '$default'
In this example, SSViewer::get_themes() will return those three items as an array in the same order: ['mytheme', 'simple', '$default]. When checking to see if a template exists, $default will then be replaced by the paths of all modules which define templates, in the same order as they appear in the manifest.
<?php
use SilverStripe\View\ThemeResourceLoader;
$templatePaths = ThemeResourceLoader::inst()->getThemePaths(SSViewer::get_themes());
$templatePaths === [
'themes/mytheme',
'themes/simple',
'mycustommodule',
'vendor/silverstripe/asset-admin',
'vendor/silverstripe/campaign-admin',
'vendor/silverstripe/reports',
'vendor/silverstripe/siteconfig',
// Some vendor modules may appear here...
'vendor/othervendor/custommodule',
'vendor/silverstripe/cms',
'vendor/silverstripe/admin',
'vendor/silverstripe/assets',
'vendor/silverstripe/framework'
];
Xcode auto-generates the class implementations for your NSMO entities - great.
But we often need to customize them. If you ever forget that you customized these files, Xcode will happily "delete" (overwrite) and remove all your code.
So ... a classic trick was to:
Create the NSManagedObject's in Apple's model view
Generate the classes
Create new classes which use Categories to extend the original classes, adding the modified behaviour
Import the custom-category-headers rather than the base NSMO headers, thereby getting the "new" behaviour
This works great: put custom code in the category, and when you auto-generate files using Xcode, you never lose anything.
But ... now I'm using Bindings / Mac OS code, and Bindings are great, but I have no idea how to make a Binding "import" the derived header (with the category, and the modified methods / custom behaviour)?
e.g. if I have an ArrayController (very common) that's holding NSMO instances, you normally tell it the "Entity Name" (e.g. "MyCoreDataEntity"), and it requests the NSMO with that class name. But that will never load the category, so it will never pick up the customized version of the class.
How do you get around this? Either: how do you load in the category-version of a class?
OR: how do you write custom code without using categories and AVOID Xcode deleting all your code when it feels like it?
I must admit since I use cocoa touch there is no binding available - so I really do not know if my suggestion is applicable in your case.
However, maybe this helps?
There is an alternative to categories for core data additions - not as "sophisticated" as categories - I know.
One may use #include statements:
There are two alternatives:
create a new ClassFile, delete the include "header.h", (delete the header.h), put the extra code there. It compiles but brings the two warnings: (which are understandable) [WARN]warning: no rule to process file '$(PROJECT_DIR)/Classes/../included_dataStuff' of type text for architecture armv6 [WARN]warning: no rule to process file '$(PROJECT_DIR)/Classes/../included_dataStuff' of type text for architecture armv7
create a new "empty" file and put the extra code there. This does not produce any warnings.
The difference between 1 and 2 is that while the code formatting remains in the first alternatve (having to accept the 2 warnings) in the second all the code format is lost and its treated like normal text (but there is no warning)
I guess I would prefer the first. Of course, the only modification to the generated code file would be the #include statement.
The easiest solution would be to subclass NSArrayController, import the category and then use the subclass in IB. That way your bindings should automatically know of the category.
MoGenerator used to be good at generating custom classes without having to overwrite anything. I'm tinkering with updating it or something like it for Xcode 4.x since the original authors don't seem to have the time to do so.
So thanks to the Visualization and Modeling Feature Pack , I can build a uml model diagram and generate a bunch of classes.
But what now? Presumably, my developers will add code to those classes. Useful code, valuable code, and as the templates themselves indicate:
// Changes to this file will be lost if the code is regenerated.
So what is the best solution here? Can I make the modeling project reflect changes to the actual classes? Should I generate partial classes? Modify the default templates to read class files and not auto-generate anything that has been modified? Should I tell developers not to edit model files under pain of....well, pain?
Thanks for the tips.
As far as I know, this is really the key reason for partial classes in the first place. The custom code goes in one file, the auto-generated in another.
You could also create classes derived from the generated ones, and put any changes in there. I also agree with above poster that partial classes could be the way to go.
Although the tools generate basic skeleton classes out of the box, that's really just a starting point. You can easily adapt the generator templates to create your own stuff. Different people want to generate different code from the classes - some even generate XML or SQL. And yep, in C#, partial classes are good to generate, so's to keep the hand-written code separate from the generated bits.
It's good to put lots of extension points in the generated code, where you fill in the details by hand code.
Another neat idea is "double derived": from each UML class, generate a base class and a derived class. The derived one has only constructors. The base class has any methods you generate. So your hand code can easily override generated methods where you need that.
There are several options in the tool and recommending what is best is hard without knowing your scenario. Partial classes are great for some, but not all applications. If you want your UML class to generate a partial class, you can set it's C# stereotype's property to "Partial" and it will do so, and custom code can then be added in a partial class that won't be overwritten. If you want to prevent code from being overwritten, you can do this by setting the overwrite property to False on the template binding that corresponds to the package you are working on. This lets you set your extension code to be in a package that is not overwritten, while your model mastered code is overwritten with the latest model changes. Finally, if you want your code to be the master for your model so it always reflects the latest code, then you can reverse engineer your code by using the architecture explorer to select your classes and then dragging them in to a UML diagram. So for a given gesture, either the model is the master or the code is the master. In this version, we did not implement automated merge capabilities between the two.
I am creating a front-end for a data collection web application. Operators using the data collection application will log data for a dozen different projects, with each project requiring different fields. There are some common fields (like name, address... etc) but then each project also has custom fields for extra data that needs to be collected. Some projects require dozens of extra fields, while some projects require only 1 or 2 fields. Can anyone think of a "clean" way to handle this situation? I don't want to create an input page for each project, and some people are tossing around the idea of doing UI templates in XML. Any guidance would be much appreciated.
XML would provide a neat solution to your problem. Depending on the user choice, ask the user to fill more fields. From your problem statement its looking that you know how many projects need extra fields and which do not. If you know this data then feed this data into a database and then accordingly generate your form page. However even if the data is available dynamically with the use of an interactive javascript and ajax you can easily achieve a neat solution.